切片与类型别名作为方法接收器

我有一个Foo带有方法的结构print:


type Foo struct {

    Bar string

}

func (f Foo) print() {

    fmt.Println(f.Bar)

}

如果我想打印一片Foo,规范的方法可能是写一个for循环,并有一个函数来封装它:


func printFoos(fs []Foo) {

    for _, f := range fs {

        f.print()

    }

}

printFoos([]Foo{})

来自 OOP 背景,我觉得这种方法有点不吸引人。


我想做的是printFoos与[]Foo:


// Invalid Go code

func (fs []Foo) print() {

    for _, f := range fs {

        f.print()

    }

}

上述方法不起作用,因为在 Go 中,不能将未命名类型用作方法接收器,如此 Google Group thread中所述。


为了规避它,可以写:


type Foos []Foo

func (fs Foos) print() {

    for _, f := range fs {

        f.print()

    }

}

要使用它,我必须将类型显式声明为Foos,所以我仍然不能使用printon[]Foo


fs := []Foo{}

fs.print() // error

var fss Foos = fs

fss.print()

我感到困惑的是,在上面的代码中,fss并且fs显然属于同一类型,因为我可以毫无错误地分配fs给它fss。但是,我们不能简单地使用fs.print()Go 并让 Go 智能转换。


为什么会这样?


一只甜甜圈
浏览 153回答 1
1回答

四季花海

我感到困惑的是,在上面的代码中,fss并且fs显然属于同一类型,因为我可以毫无错误地分配fs给它fss。你跳到错误的结论。具有相同的类型并不是可分配性的必须要求。fss有 type Foos,并且fs有 type []Foo,一个未命名的切片类型。确实,它们具有相同的基础类型,这就是您可以分配fs到的原因fss,这在此可分配性规则中有所涵盖:如果以下条件之一适用,则值x可分配给类型的变量T(“x可分配给”):T...x的类型V,并且T具有相同的基础类型,并且至少有一个V或T不是定义的类型。方法绑定到具体类型。因此,该Foos.print()方法不适用于其他类型的值,包括[]Foo.但是您不需要创建变量来调用该方法,您可以简单地使用类型转换:Foos(fs).print()这种转换不改变内存布局,只改变类型,因此安全高效。我们仅使用它来访问具有相同基础类型的类型的方法。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go