独家新闻日记

华为认证,广州景点,耳机品牌-蜗牛连接王

有两种办法能够将参数传递给函数。一个按值传递,另一个按引证传递。这两种办法都有不同的概念,有时会给程序员带来困惑。

简略来说,传递值是指咱们传递参数时没有指向该值的原始地址的指针。而且通过引证传递是当咱们运用指向给定参数的指针传递参数时。

在Golang中,咱们能够鄙人面的示例中看到这两个。

func passByValue(item string){} 
func passByReference(item * string){}

在Golang中通过引证传递和值传递

一个简略得比如:

package main
import (
"fmt"
)
func main() {
item := ""
passByValue(item)
fmt.Println(item)
passByReference(&item)
fmt.Println(item)
}
func passByValue(item string) {
item = "hello"
}
func passByReference(item *string) {
*item = "world"
}

上面的示例显现了咱们能够依据类型(通过引证或值)传递参数的典型办法。

Golang中的接口参数传递参阅

可是,有一天。我遇到了一个问题,我需求处理有关通过引证传递参数的问题。不像我从前做过的任何一般的,这个在参数中运用接口。所以基本上,这个函数承受任何内容interface{},并依据该函数内部发作的逻辑填充值。

该功用如下所示。

func doSomethinWithThisParam(item interface {}){}

这个函数很简略,它只承受一个接口,并在其间做一些作业。它不会回来任何过错,因而它仅仅用项中的值来水合项目。

因而,为了处理这种古怪的行为,我企图通过自己测验来处理。下面我将解说我怎样处理它的过程。

第一次测验:指向接口的指针

package main
import (
"fmt"
)
func main() {
var item Student
doSomethinWithThisParam(&item)
fmt.Printf("%+v", item)
}
type Student struct {
ID string
Name string
}
func doSomethinWithThisParam(item *interface{}) {
*item = &Student{
ID: "124",
Name: "Iman Tumorang",
}
}

这一个无法编译,它抛出过错。

cannot use &item (type *Student) as type *interface {} in argument to doSomethinWithThisParam: *interface {} is pointer to interface, not interface

第2次测验:直接为接口分配值

我测验没有指向接口的指针,但相反,我将值直接分配给给定的参数。

func doSomethinWithThisParam(item interface{}) {
item = &Student{
ID: "124",
Name: "Iman Tumorang",
}
}
// Print: {ID: Name:}

打印完数据后,它仍无法正常作业。它打印空值。

第三次测验:转化为原始类型并分配值

后来,在测验了许多东西后,我发现了一个有用的东西。该参数仍然是一个接口,但不是直接赋值,而是首要我有必要将其强制转化为原始类型。这时,它有点扎手。咱们有必要当心怎样运用它。请参阅下面的差异。

下面这个比如没有用。

func doSomethinWithThisParam(item interface{}) {
origin := item.(*Student)
origin = &Student{
ID: "124",
Name: "Iman Tumorang",
}
item = origin
}
// Print: {ID: Name:}

可是这就正常了。

func doSomethinWithThisParam(item interface{}) {
origin := item.(*Student)
origin.Name = "Iman Tumorang"
origin.ID = "124"
}
// Print: {ID:124 Name:Iman Tumorang}

What?????

起先,我有点困惑。这儿究竟发作了什么?怎样可能在我这样做的时分它不起作用。

origin := item.(*Student)
origin = &Student{
ID: "124",
Name: "Iman Tumorang",
}

但有了这个,它起作用了。

origin := item.(*Student)
origin.Name = "Iman Tumorang"

需求几分钟来处理这个问题。但后来我理解为什么会这样。

在处理问题后,我认识到了一些作业。第一个失利,由于它替代了地址。因而,为了替换地址,我测验了一种只改动价值的新办法。

func doSomethinWithThisParam(item interface{}) {
origin := item.(*Student)
*origin = Student{
ID: "124",
Name: "Iman Tumorang",
}
item = origin
}
// Print: {ID:124 Name:Iman Tumorang}

终究的解析器

因而,通过屡次实验的实验,最终我挑选了最终一个。而且由于我正在处理的这个函数将依据我当时的使命进行一些通用,我将其转化并增加开关事例条件,以便依据我制造的开关事例愈加通用。

简略来说,我在当时使命中的一切作业都能够鄙人面的比如中描绘。有一个通用函数能够承受接口并在其间做一些作业。它支撑许多结构。

代码段如下:

package main

import (
"fmt"
)

func main() {
var item Student
doSomethinWithThisParam(&item)
fmt.Printf("%+v", item)
}

type Student struct {
ID string
Name string
}

func doSomethinWithThisParam(item interface{}) {
switch v := item.(type) {
case *Student:
*v = Student{
ID: "124",
Name: "Iman Tumorang",
}
// another case
}
}

定论

这个在Golang真的是十分严厉的作业。运用pass-by-reference和interface {}时,咱们有必要十分当心。为了防止任何不必要的过错,我主张为每个运用pass-by-reference办法的函数增加单元测试。

说实话,我在这个问题上被困了一个小时。因而,如果您以为这是一件功德,请共享这篇文章,这样任何人都不会遇到相同的问题。

推荐新闻