gpt4 book ai didi

pointers - 在 Go 中,您将如何访问传递给期望空接口(interface)的函数的底层数组?

转载 作者:IT王子 更新时间:2023-10-29 02:05:54 26 4
gpt4 key购买 nike

假设我们有一个如下形式的函数:

func WorkMagic(obj interface{}) interface{} {
switch t := obj.(type) {
case string:
// Do string magic
default:
// Do slice magic
}
...
}

我希望 obj 是字符串或 slice ,我可以通过开关确定。在 slice 的情况下,我希望能够对任意 slice 进行排序工作,而不管类型如何。似乎实现此目的的最佳方法是以与 this article 中讨论的类似方式使用不安全包。 .

然而,这里的函数接受特定类型的 slice ([]string),而我希望能够处理任何 slice 。所以问题是,假设我接受一个空接口(interface)作为输入,我如何使用 unsafe.Pointer 访问底层 slice/数组以便能够循环并修改哪个值与哪个索引相关联?

最佳答案

您需要使用 reflection .它使您能够通用地工作,而不会像 unsafe 那样放弃类型和内存安全。阅读 Go 博客的 Laws of Reflection .

func actOnSlices(i interface{}) {

v := reflect.ValueOf(i)

for v.Kind() == reflect.Ptr { // dereference pointers
v = v.Elem()
}

if v.Kind() != reflect.Slice { // ensure you actually got a slice
panic("given argument is not a slice")
}

// do slice stuff

}

编辑以回答您的第二个问题:

是的——这是可以做到的: slice 的元素是可寻址的,因此是可设置的。查看following working example :

package main

import (
"fmt"
"reflect"
)

func main() {
s := []string{"foo", "bar"}
fmt.Println(swapIndexes(s, 0, 1)) // prints [bar foo]
}

func swapIndexes(i interface{}, x, y int) interface{} {

v := reflect.ValueOf(i)

for v.Kind() == reflect.Ptr { // dereference pointers
v = v.Elem()
}

if v.Kind() != reflect.Slice { // ensure you actually got a slice
panic("given argument is not a slice")
}

t := v.Index(x).Interface()

v.Index(x).Set(v.Index(y))

v.Index(y).Set(reflect.ValueOf(t))

return v.Interface()

}

编辑以回答您的第三个问题:

unsafe 包在用户代码中不会经常遇到。它的存在是为了实现某些需要规避 Go 的安全保证才能工作的特性(例如反射、C 交互)。顾名思义,使用 unsafe 是不安全的,因为您可能会在不知不觉中搞砸大事。通过使用 unsafe,您需要付出很大的代价,所以最好还是值得。引用@twotwotwo:

The downside of unsafe is that if you mess up you're in the old days of segfaults, memory corruption, and buffer-overflow security holes.

此外,正如@twotwotwo 所建议的那样;重复代码比使用反射实现通用性更“像 Go”。

对于 Go 的类型系统,[]string[]int 是两个完全独立且不相关的类型。就像 intstring 一样。这种关系(都是 slice )只对程序员来说是显而易见的。不说一片什么就无法表达“一片”。

关于pointers - 在 Go 中,您将如何访问传递给期望空接口(interface)的函数的底层数组?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25551082/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com