通过引用设置接口参数

2024-02-01

我很难理解如何设置作为指针传递的接口值。我正在尝试完成以下任务:

import "fmt"

var Stuff map[string]interface{}

func main() {
    var num int
    Stuff["key"] = 9001
    get("key", &num)
    fmt.Println("num:", num)
}

func get(k string, v interface{}) {
    *v = Stuff[k]
}

我需要做什么才能使我的程序输出

num: 9001

编辑:是否有可能使用的包罗万象的解决方案reflect?


您可以使用以下方式模拟 AppEngine 数据存储界面reflect http://golang.org/pkg/reflect/;通常我会说最小化反射,但是您(以及 AppEngine 和其他 ORM)在这里没有其他很好的选择来呈现您想要的界面。对于模仿的东西Get you:

  • get a reflect.Value with ValueOf()
  • 获取您想要创建的事物的类型
  • 创建它与reflect.Zero
  • 可选地填写一些数据reflect.Field(), etc.
  • use reflect.Indirect() and Value.Set()通过指针设置原稿。

一个简单的例子,只是通过指针将结构清零,位于http://play.golang.org/p/g7dNlrG_vr http://play.golang.org/p/g7dNlrG_vr并复制到这里:

package main

import (
    "fmt"
    "reflect"
)

func main() {
    i := 1
    clear(&i)
    fmt.Println(i)
}

func clear(dst interface{}) {
    // ValueOf to enter reflect-land
    dstPtrValue := reflect.ValueOf(dst)
    // need the type to create a value
    dstPtrType := dstPtrValue.Type()
    // *T -> T, crashes if not a ptr
    dstType := dstPtrType.Elem()
    // the *dst in *dst = zero
    dstValue := reflect.Indirect(dstPtrValue)
    // the zero in *dst = zero
    zeroValue := reflect.Zero(dstType)
    // the = in *dst = 0
    dstValue.Set(zeroValue)
}

用于模拟GetMulti您需要更多步骤来处理切片。一个例子是在http://play.golang.org/p/G_6jit2t-2 http://play.golang.org/p/G_6jit2t-2及以下:

package main

import (
    "fmt"
    "reflect"
)

func main() {
    s := []int{}
    getMultiZeroes(&s, 10)
    fmt.Println(s)
}

func getMultiZeroes(slicePtrIface interface{}, howMany int) {
    // enter `reflect`-land
    slicePtrValue := reflect.ValueOf(slicePtrIface)
    // get the type
    slicePtrType := slicePtrValue.Type()
    // navigate from `*[]T` to `T`
    sliceElemType := slicePtrType.Elem().Elem() // crashes if input type not `*[]T`
    // we'll need this to Append() to
    sliceValue := reflect.Indirect(slicePtrValue)
    // and this to Append()
    sliceElemValue := reflect.Zero(sliceElemType)

    // append requested number of zeroes
    for i := 0; i < howMany; i++ {
        // s := append(s, v)
        sliceValue.Set(reflect.Append(sliceValue, sliceElemValue))
    }
}

在实时代码中(与您正在进行的测试相反),使用类型开关(如 Martin 建议的那样)会更快,以便为每种类型运行专门的本机代码;如果您按类型有不同的行为,这也可能很方便。一个例子GetMulti is at http://play.golang.org/p/q-9WyUqv6P http://play.golang.org/p/q-9WyUqv6P及以下:

package main

import "fmt"

func main() {
    s := []int{}
    getZeroes(&s)
    fmt.Println(s)

    fails := []float32{}
    getZeroes(&fails)
}

func getZeroes(slicePtrIface interface{}) {
    switch sp := slicePtrIface.(type) {
    case *[]int:
        (*sp) = append((*sp), 0, 0)
    case *[]string:
        (*sp) = append((*sp), "", "")
    default:
        panic(fmt.Sprintf("getZeroes: passed type %T, which is not a pointer to a slice of a supported type", slicePtrIface))
    }
}

你甚至可以简单地将两者结合起来;为常见类型编写自定义代码并调用慢速reflect默认情况下基于 - 的版本。演示地址:http://play.golang.org/p/6qw52B7eC3 http://play.golang.org/p/6qw52B7eC3(不是复制,因为它是上述两者的简单拼接)。

恰巧有最近的另一个问题 https://stackoverflow.com/questions/26764907/why-cant-i-use-reflection-to-take-the-address-of-a-slice/26765210#26765210关于如何传递一个值GetMulti,而不是模仿GetMulti本身,如果出现的话。


更多的是作为一般参考而不是回答这个问题:

了解“Go 缺乏引用传递”很有用,但也需要一些阐述。 Go 有指针,以及其他类型,例如包含数据指针的切片。不存在“按引用传递”的含义只是 Go 永远不会更改值参数(int, struct) 隐式转换为指针。 C++ 引用参数正是这样做的:C++void f(i int&) { i++; }变化i在调用者中,无需调用者在调用点显式传递指针。func (i int) { i++ }没有。

在 Go 中,您可以查看传递给函数调用的类型并了解它可以更改哪些数据。使用 C++ 引用参数或某些语言的“按引用传递”语义,any通话可能会改变当地人;如果不查看声明,你就无法判断。

为了避免不必要的数据复制,切片、字符串、映射、接口和通道值的实现中已经存在指针。在这些类型中,指针、切片和映射实际上允许您通过它们修改数据。此外,与 C++ 一样,Go 的this-like 接收者参数可以是一个没有显式的指针&在调用代码中。有更多关于此的内容Russ Cox 的 godata 帖子 http://research.swtch.com/godata and 关于何时需要指针的总结 https://stackoverflow.com/questions/23542989/pointers-vs-values-in-parameters-and-return-values/23551970.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

通过引用设置接口参数 的相关文章

  • 是否可以在 C# 中强制接口实现为虚拟?

    我今天遇到了一个问题 试图重写尚未声明为虚拟的接口方法的实现 在这种情况下 我无法更改接口或基本实现 而必须尝试其他方法 但我想知道是否有一种方法可以强制类使用虚拟方法实现接口 Example interface IBuilder
  • 如何将接口转换为接口切片?

    我的输入是interface 而且我知道它可以是任何类型的数组 我想读取我输入的元素之一 所以我尝试将我的interface 进入一个 interface 但是 go 会给我以下错误 恐慌 接口转换 interface 是 map stri
  • 是否可以使用打字稿映射类型来创建接口的非函数属性类型?

    所以我正在研究 Typescript 的映射类型 是否可以创建一个接口来包装另一种类型 从而从原始类型中删除函数 例如 interface Person name string age number speak void type Data
  • golang无法启动调试,显示未找到框架CoreFoundation

    我使用的是 Macbook pro m1 在数据迁移或更新到 monterey 后 不确定是什么原因导致的 golang 似乎无法调试或 go list 编译 我尝试重新安装 更新 golang 结果是一样的 Go版本 1 17 3 dar
  • Golang 中的确定性 RSA 加密 - 如何在多次加密下为给定消息获得相同的结果

    对于下面的RSA加密代码 每次对同一条消息进行加密时 结果都会不同 我发现这是由于rand Reader in the rsa EncryptOAEP功能使其更加安全doc https pkg go dev crypto rsa Encry
  • 使用 Typescript 检查接口类型

    这个问题是直接类比使用 TypeScript 检查类类型 https stackoverflow com questions 12789231 class type check with typescript 我需要在运行时查明任何类型的变
  • 使用 mgo 驱动程序进行 mongo 聚合查询

    我在 mongodb 中有以下查询 db devices aggregate match userId v73TuQqZykbxFXsWo state true project userId 1 categorySlug 1 weight
  • VLC 媒体播放器有 C# 界面吗? [关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 是否可以使用 C 控制台应用程序中的包装器从 VLC 播放中当前播放的文件中读取曲目统计信息 时间 标
  • 为什么不直接使用 DateTime.Now 呢?

    最近一直在努力学习接口方面的知识 我看到了这段代码 但无法理解为什么你不直接使用DateTime Now在其自己的 我不确定为什么这个界面很有用 有人可以解释一下吗 这本书的作者试图解释 但我不太明白如何按照他们所说的方式实现它 程序员是否
  • 关闭长度未知的通道

    当不了解频道时我无法关闭频道 length package main import fmt time func gen ch chan int var i int for time Sleep time Millisecond 10 ch
  • Facebook服务器端登录、CORS

    我正在实现一个带有 FB 服务器端登录的网站 简化步骤如下 一个简单的按钮触发 JS 脚本 该脚本调用我的后端 APIhttps localhost fblogin function sendFbLoginData get https lo
  • go json marshal 的默认大小写选项?

    我有以下结构要导出为 json type ExportedIncident struct Title string json title Host string json host Status string json status Dat
  • 如何对结构切片而不是切片结构进行范围调整

    稍微玩了一下 Go HTML 模板后 我发现的所有循环模板中对象的示例都是将切片结构传递给模板 有点像这个示例 type UserList struct Id int Name string var templates template M
  • 从 Golang 调用 C 函数

    我想在 Golang 中编写控制器逻辑并处理 json 和数据库 同时在 C 中使用我的数学处理模型 在我看来 调用 C 函数的开销必须尽可能低 就像设置寄存器 rcx rdx rsi rdi 一样 执行一些操作fastcall 并获取 r
  • 所有可能的 GOOS 价值?

    如果我做对了 GOOS在编译源代码时确定 为了更好地支持多个操作系统 我感兴趣的是GOOS可能 当然 Go 是开源的 所以它可能有无限的可能性 所以我真正想要的是一个 通用列表 已知值为 windows linux darwin or fr
  • golang中如何将相对路径解析为绝对路径?

    节点中是否有类似 path resolve 的API 或者有什么东西可以做同样的事情 例如 nodejs代码 path resolve sample sh 应该得到 home currentuser sample sh 解决 表示用户主目录
  • 比较:接口方法、虚方法、抽象方法

    它们各自的优点和缺点是什么 接口方法 虚拟方法 抽象方法 什么时候应该选择什么 做出这一决定时应牢记哪些要点 虚拟和抽象几乎是一样的 虚方法在基类中有一个实现 可以选择重写 而抽象方法则没有 并且must在子类中被覆盖 否则它们是相同的 在
  • java中将函数作为参数传递

    我正在熟悉 Android 框架和 Java 并希望创建一个通用的 NetworkHelper 类 该类将处理大部分网络代码 使我能够从中调用网页 我按照developer android com 上的这篇文章创建了我的网络类 http d
  • 管理多租户 ArangoDB 连接

    我使用 ArangoDB Go 使用 go driver 并且需要实现多租户 这意味着每个客户都将在单独的数据库中拥有他的数据 我想要弄清楚的是如何使这种多租户发挥作用 我知道为每个请求创建一个新的数据库连接是不可持续的 这意味着我必须维护
  • 使用生成的 Golang DLL 返回字符串或 *C.Char

    我一直在努力追随z505 goDLL https github com z505 goDLL回购并遇到了一个大问题 该方法无法返回字符串 我无法读取结果的输出变量 这是我到目前为止使用的代码 Go 完整代码https play golang

随机推荐

  • 如何在没有 jQuery 的情况下提交表单而不重新加载页面?

    我的表单如下 它需要向我的 java Servlet 发送一个操作来更新数据库 如何在不重新加载页面的情况下提交表单 目前与action myServlet 它不断将我引导到新页面 如果我删除对 myServlet 的操作 输入不会添加到我
  • 模拟器无法升级 xcode 10?

    将 Xcode 9 4 1 更新到 Xcode 10 后 没有任何模拟器可以构建 iOS 应用程序 我的 iOS 应用程序在 Xcode 9 4 1 上完美构建并运行 我有多个这样的警告 警告 iOS Simulator 部署目标设置为 7
  • 将环境变量传递给 Angular2 应用程序?

    我需要将后端 url 传递到我的 Angular2 应用程序 因为生产服务器和开发服务器托管在不同的位置 我知道我可以将这些东西存储在外部 config json 中并在启动时加载 然而 在应用程序启动之前 这似乎是不必要的对服务器的额外调
  • 具有多个条件和列表的 COUNTIF

    我需要计算满足 CRITERIA 1 满足 CRITERIA 2 以及 CRITERIA 3 属于 E 列中包含的值集的单元格数量 我目前正在使用以下公式 SUM COUNTIFS A2 A11 TRUE B2 B11 TRUE C2 C1
  • Haskell 中的 fromInteger 重写

    所以我喜欢Haskell 但对Num类不满意 所以我想为代数类型创建我自己的类型类层次结构 问题是 即使我导入 Prelude 隐藏 Num 以及与之相关的所有内容 使文字 1 具有类型 t 的唯一方法仍然是使 t 实例 Num 我很想从
  • .Net C# String.Join 如果元素值为 null,如何输出“null”而不是空字符串?

    根据String Join 的 MSDN 文档 http msdn microsoft com en us library 57a79xd0 aspx 如果 value 中的任何元素为 null 则使用空字符串 我的代码从数据表中提取数据
  • 如何将 Unix 'Top' 命令输出捕获到 CSV 文件?

    我正在尝试获取前 5 行top通过 shell 脚本命令 我需要将输出写入csv文件 我需要每 15 秒监控一次结果 最后 我需要使用获得的数据表绘制图表 我得到了 shell 脚本来编写前 5 行top命令给一个txt file bin
  • -fomit-frame-pointer *总是*省略 fp 吗?

    是否 fomit frame pointeralways省略帧指针 是否存在pc和fp都需要设置的情况 动态堆栈增长是否会强制设置 fp 专门询问MIPS32 谢谢 正确执行并不真正需要帧指针 除非有时异常展开 动态堆栈增长通常需要某种帧指
  • 管理加载 ZipFile 时分配的内存

    我正在尝试将 69 930 个文件加载到基本文本编辑器中 一切都很顺利 全部加载完毕后 内存就达到了非常酷的 130MB 然而 在高峰加载时间期间 最大容量可达 900MB 1200MB 内存全部引用Inflater buf http gr
  • C++ 重载模式:使用可变 lambda 进行调用解析

    考虑这个众所周知的 C 模式 template
  • 如何获取远程桌面客户端的IP地址?

    我正在尝试编写一个脚本来记录用户启动远程桌面以登录 Windows Server 的 Windows 客户端的 IP 地址 如何在服务器中捕获客户端的IP地址 所以 你忽略代理 在域中使用环境变量 CLIENTNAME 您可以将其解析回IP
  • wordpress:polylang 插件的媒体库问题

    我正在使用 Wordpress 开发一个网站 其中使用 Polylang 插件为多种不同语言制作内容 我使用 Polylang 来表示两种语言 荷兰语 主要 和英语 次要 当我在荷兰语页面上传图像时 一切都很好 但是当我创建一个英文页面 并
  • 使用 PIL 的 ImageDraw 模块

    我正在尝试使用 PIL 的 ImageDraw 模块进行单独的像素操作 下面的代码应该创建 Tkinter 画布小部件 然后打开一张图像 将一个像素的颜色更改为红色 然后将图像嵌入到画布小部件中 但是 它似乎不起作用 My Code imp
  • 如何在 Visual Studio 2012 中编辑 SSRS 2008R2 报告?

    我是一名报告编写者 能够在 Visual Studio 2008 中编辑 更新报告 我们使用 SSRS2008R2 我刚刚安装了 Visual Studio 2012 当我去转换我的报告项目时 它无法工作 因为我似乎缺少一个组件 本质上 项
  • Kafka 连接集群设置或启动连接工作线程

    我正在通过 kafka connect 我正在尝试了解这些概念 假设我已经设置了 kafka 集群 节点 k1 k2 和 k3 并且它正在运行 现在我想在不同节点 例如 c1 和 c2 中以分布式模式运行 kafka 连接工作程序 几个问题
  • 从未在数据库上显式调用 Close

    我有一个来自 sqlite 数据库的列表视图 我在几个不同的点调用 fillData 来更新列表视图 private void fillData readDatabase open Cursor itemsCursor readDataba
  • 在Android模拟器中,是否可以注意到振动效果?

    很简单的问题 是否可以注意到 Android 模拟器中的振动 我猜你想知道是否发生了振动 如果是这样 请查看模拟器中的 logcat 中的振动消息
  • Delphi 2010 中的 Indy IdHttp Post 问题

    我对 Indy IdHttp Post 方法有问题 使用 Delphi 2007 编译的函数 CallRpc 工作正常 但使用 Delphi 2010 编译的相同代码会引发异常 当我将 Delphi 2007 Indy TIdHttp 更改
  • 使用 Swift 3 停止预定定时器,即使定时器为零,定时器也会继续触发

    我们调用startTimer函数来启动一个定时器 当我们想要停止它时 我们调用 stopTimerTest 函数 但在调用 stopTimer 函数后 timerTestAction 继续触发 为了检查计时器条件 我们使用 print 并在
  • 通过引用设置接口参数

    我很难理解如何设置作为指针传递的接口值 我正在尝试完成以下任务 import fmt var Stuff map string interface func main var num int Stuff key 9001 get key n