如何在Golang中将nil接口转换为结构体

huangapple go评论78阅读模式
英文:

How to make nil interface to struct in golang

问题

我是你的中文翻译助手,以下是代码的翻译:

我是Golang的新手。
我执行了下面的代码。最后得到了一个空的humans数组。
在函数F中我应该做什么?

为了测试(猴子补丁)的目的,我必须按照原始函数的调用方式进行操作。

package main

import (
	"fmt"
)

type Human struct {
	Name string
}

type Cat struct {
	Name string
}

func F(arr interface{}) {
	switch arr.(type) {
	case *[]*Human:
		arr = &[]*Human{{Name: "abc"}}
		arr = arr.(*[]*Human)

	case *[]*Cat:
		arr = &[]*Cat{{Name: "meow"}}
		arr = arr.(*[]*Cat)
	}

}

func main() {

	var humans []*Human
	F(&humans)
	fmt.Println(humans)

	var cats []*Cat
	F(&cats)
	fmt.Println(cats)
}

希望对你有帮助!

英文:

I'm new in Golang.
I executed the code below. I get empty humans array in the end.
What should I do in func F?

For testing(monkeypatch) sake. I have to follow the way how the origin func is called.

package main

import (
	"fmt"
)

type Human struct {
	Name string
}

type Cat struct {
	Name string
}

func F(arr interface{}) {
	switch arr.(type) {
	case *[]*Human:
		arr = &[]*Human{{Name: "abc"}}
		arr = arr.(*[]*Human)

	case *[]*Cat:
		arr = &[]*Cat{{Name: "meow"}}
		arr = arr.(*[]*Cat)
	}

}

func main() {

	var humans []*Human
	F(&humans)
	fmt.Println(humans)

	var cats []*Cat
	F(&cats)
	fmt.Println(cats)
}

答案1

得分: 2

答案和主要问题的原因是,当参数传递给函数或赋值给变量时,Go 总是使用按值传递(或值的副本)。

你的函数 F 接受一个 arr 参数:

func F(arr interface{}) {
    //...
}

当从你的 main 函数调用时,你传递了一个 []*Human 指针作为参数,这些值将被复制并传递给你的函数 F 进行执行。

回到你的函数 F 的主体,arr 将具有由 main 传递的相同值,这恰好是指向原始 []*Human 结构体的地址。在给 arr 赋予新值时:

func F(arr interface{}) {
    switch arr.(type) {
    case *[]*Human:
        arr = &[]*Human{{Name: "abc"}}
        // ...
    }
}

你正在将新值赋给 局部arr 变量,而不是原始指针,原始指针保持不变。

要更新参数指针所指向的值,你应该使用 解引用 符号:

func F(arr interface{}) {
    switch arr := arr.(type) {
    case *[]*Human:
        *arr = []*Human{&Human{Name: "abc"}}
        fmt.Println(arr)
    // ...
    }
}

> 注意 switch arr := arr.(type) 语句,它创建一个新的 arr 变量(遮蔽了参数 arr),并具有 interface 的动态类型,以便能够为其分配适当的值。

英文:

The answer, and the main issue cause as well, is that Go always uses pass by value (or copy of the value) when arguments are passed around to function or assigned to variables.

Your function F takes an arr argument:

func F(arr interface{}) {
    //...
}

When called from your main function, you are passing an []*Human pointer as an argument, which values will be copied and fed to your function F for execution.

Going back to your function F body, the arr will be having the same value passed by main, which happens to be the address to the original []*Human struct. Upon assigning a new value to arr:

func F(arr interface{}) {
    switch arr.(type) {
    case *[]*Human:
        arr = &[]*Human{{Name: "abc"}}
        // ...
    }
}

You are assigning a new value to the local arr variable and not to the original pointer, which remains, indeed, unchanged.

To update the value toward which the argument pointer is referring to, you should used the dereferrence symbol:

func F(arr interface{}) {
	switch arr := arr.(type) {
	case *[]*Human:
		*arr = []*Human{&Human{Name: "abc"}}
		fmt.Println(arr)
    // ...
	}
}

> Note the switch arr := arr.(type) statement which creates a new arr variable (shadowing the argument arr) with the interface dynamic type to be able to assign the proper value to it.

huangapple
  • 本文由 发表于 2022年7月24日 18:58:56
  • 转载请务必保留本文链接:https://go.coder-hub.com/73097775.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定