【问题标题】:Dynamic argument and Generic type动态参数和通用类型
【发布时间】:2019-10-07 22:13:27
【问题描述】:

我有以下代码:

package main

import (
    "fmt"
)

func test(data interface{}) {
    data = "123"
}

func main() {
    t := "org"
    test(&t)
    fmt.Println(t)

    e := 1
    test(&e)
    fmt.Println(e)
}

我尝试添加指向 *interface{} 的指针,但它会引发错误,如何在打印时将字符串“test”分配给 t?现在t 将打印为“org”

我问是因为我不确定我在这里如何使用动态类型,例如josn.Unmarshal(data []byte, v interface{})我使用了这个函数,只要我们传递引用,它就可以将databyte转换为我们想要的任何类型。

【问题讨论】:

    标签: pointers go interface


    【解决方案1】:

    我认为您期望 interface 比实际情况更神奇。

    考虑你的程序的这个变体:

    package main
    
    import (
        "fmt"
    )
    
    func test(p *string) {
        s := "test"
        p = &s
    }
    
    func main() {
        t := "org"
        test(&t)
        fmt.Println(t)
    }
    

    您希望这会打印出test 吗?如果是这样,我们有一个更大的问题。 :-) 如果不是,你为什么期望p interface{} 的版本在直接分配给p 时会更改t

    如果我们把test改成*p

    func test(p *string) {
        *p = "test"
    }
    

    程序确实打印test,正如你所料。

    现在剩下的就是处理p 被声明为data interface{} 的情况。和bserdar's answer一样,必须先从data中的接口对象中提取底层的*string指针。然后,您可以使用该指针设置main 的变量t。您可以通过两个步骤来做到这一点:

    func test(data interface{}) {
        p := data.(*string)
        *p = "test"
    }
    

    例如,或者您可以在一行中完成所有操作。

    【讨论】:

    • 但是,如果你使用这个解决方案,如果data 不是string,程序会崩溃,在这种情况下,函数应该test(data string),因为这就是它所期望的参数。
    • 感谢您的重播,我正在使用接口{},因为我喜欢接受任何可能类型的参数,我在库中看到了json.Unmarshal(data []byte, v interface{}) 函数,它接受所有类型并坚持指针在那里,我想知道他们是如何实现它的。顺便说一句,我是 Golang 的新手。是 Java 开发人员
    • 正如 Adrian(几乎?)所说,通过使用 interface{},您有机会在您的函数 test 中检查您实际获得的类型和值。执行data.(*string) 断言——无需先测试——你得到的类型是*string。编译器插入运行时类型检查以查看是否为真,如果不是,则调用panic
    • 通常,如果test 应该能够处理,例如*string*int,则可以使用interface{}。然后你会写test检查它是否得到*string*int,并在此基础上做任何你认为正确的事情。更通用的是——以显着的运行时成本——你可以做json.Unmarshal 所做的事情,并使用reflect 包来检查你得到的接口值。函数test 越通用,编写起来就越困难,需要的运行时代码就越多,所以要确保结果与费用一样有价值。
    • 请注意,如果您只想处理 *string*int,编写两个单独的函数要容易得多,并且在编译时是安全的,一个使用 *string,另一个使用*int。可让您获得编译时安全性类型灵活性(以一定的编译时成本)的泛型将出现在 Go 2 中。
    【解决方案2】:

    您正在设置接口,而不是基础值。相反,你应该这样做

    func test(data interface{}){
      *data.(*string) = "aaa"
    }
    

    即先获取底层字符串指针,再设置它所指向的字符串。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-09-30
      • 1970-01-01
      • 2011-02-28
      • 1970-01-01
      • 2021-01-15
      相关资源
      最近更新 更多