Go: “disappearing method” in method collection

Permalink to this article – https://ift.tt/30uHFdp

In “The First Lesson of Go Language” , I spent three lessons to give a comprehensive and detailed explanation of Go methods, and the method set of types is one of the key points, because the method set determines the implementation of the interface , and the courses are also classified into different categories. Types defined using the type embedding mechanism are described, explaining the rules for forming a collection of methods for these types. I also provide a helper function that can output a certain type of method collection, so that you can easily view a specific type of method collection.

The students also invested a lot of enthusiasm in learning the Go method collection, and asked many good questions. No, a student Aeins raised a very good question two days ago. The question is as follows (slightly polished):

 Aeins:下面示例中的结构体类型使用两种不同方式嵌入接口类型。由于接口类型嵌入允许重名方法,因此I接口有三个方法。类型SI嵌入了接口类型I,因此,SI也有三个方法; SI12嵌入了接口类型I1和I2, 但SI12却只有两个方法。难道是结构体类型嵌入不允许重名,M 方法被自动隐藏了?, package main import ( "fmt" "reflect" ) type I1 interface { M() M1() } type I2 interface { M() M2() } type I interface { I1 I2 } type SI struct { I } type SI12 struct { I1 I2 } func main() { var si SI var si12 SI12 DumpMethodSet(si) DumpMethodSet(si12) } func DumpMethodSet(i interface{}) { dynTyp := reflect.TypeOf(i) if dynTyp == nil { fmt.Printf("there is no dynamic type\n") return } n := dynTyp.NumMethod() if n == 0 { fmt.Printf("%s's method set is empty!\n", dynTyp) return } fmt.Printf("%s's method set:\n", dynTyp) for j := 0; j < n; j++ { fmt.Println("-", dynTyp.Method(j).Name) } fmt.Printf("\n") } ============ main.SI's method set: - M - M1 - M2 main.SI12's method set: - M1 - M2

From the sample code of this question, we can see the question of the student Aeins: by embedding the method set of the type SI of the interface type I that combines I1 and I2, the method M is included, and by directly embedding the interface types I1 and I2 The method M in the method collection of type SI2 has “disappeared”. Why ?

Well, let’s analyze it below.

We know that the methods in a type’s method collection should all be legally callable by this type of instance. for example:

 // https://go.dev/play/p/gGkgsGRJpHv package main type I interface { M1() M2() } type T struct { } func (T) M1() { } func (T) M2() { } type S struct { I } func (S) M3() {} func main() { var s = S{ I: T{}, } s.M1() s.M2() s.M3() }

There are three methods in the method set of the structure type S, among which M1 and M2 come from the type embedding of the interface type I, and M3 is a custom method of S. But no matter which method it is, once it enters the method set of S, it can be legally called by the S instance .

Conversely: only methods that can be called directly by an instance of a type can enter its method collection . So let’s look at SI and SI12 in the question example separately.

Let’s analyze SI first. SI embeds interface type I, and interface type I is composed of two interface types, I1 and I2. This way of creating a new interface type by embedding other interface types was constrained before Go 1.14 : if the new interface type embeds multiple interface types, the method sets of these embedded interface types cannot intersect, and the embedding The method name in the method collection of the interface type of the new interface cannot have the same name as other methods in the new interface. But since Go 1.14, the Go language has removed these constraints, which is why the method sets of I1 and I2 intersect, but can still be embedded in SI at the same time. In this way, the method set of interface type SI includes M, M1 and M2.

When SI is defined by embedding I, the method set of SI “inherits” the method set of interface type I, and through a properly initialized instance of SI, we can legally call M, M1, and M2:

 type S3 struct { } func (S3) M() { } func (S3) M1() { } func (S3) M2() { } func main() { var s = SI{ I : S3{}, } sM() //ok s.M1() //ok s.M2() //ok }

Let’s look at SI12 again. In the problem example, SI12 does not embed interface type I which integrates I1 and I2, but directly embeds I1 and I2. So will the methods in the method sets of I1 and I2 become the methods in the method set of the SI12 type? It depends on whether an instance of the SI12 type can legally call the methods of I1 and I2? Let’s look at the following example:

 type S1 struct { } func (S1) M() { } func (S1) M1() { } type S2 struct { } func (S2) M() { } func (S2) M2() { } func main() { var si12 = SI12{ I1: S1{}, I2: S2{}, } DumpMethodSet(si12) si12.M1() // ok si12.M2() // ok si12.M() // ambiguous selector si12.M }

We see that the M1 and M2 methods can be successfully called through an instance of the SI12 type, but there is an “ambiguity” when calling the M method, and the Go compiler cannot determine whether to call the si12.I1.M method or the si12.I2.M method, That is, the Go compiler cannot legally call the M method, so the M method cannot be included in the method set of SI12 due to the pending ambiguity.

This is the reason why method M “disappears” in the SI12 type method collection. Did you get it!


“Gopher Tribe” Knowledge Planet aims to create a high-quality Go learning and advanced community! High-quality first published Go technical articles, “three-day” first published reading rights, analysis of the current situation of Go language development twice a year, read the fresh Gopher daily 1 hour in advance every day, online courses, technical columns, book content preview, must answer within six hours Guaranteed to meet all your needs about the Go language ecosystem! In 2022, the Gopher tribe will be fully revised, and will continue to share knowledge, skills and practices in the Go language and Go application fields, and add many forms of interaction. Everyone is welcome to join!

img{512x368}

img{512x368}

img{512x368}

img{512x368}

I love texting : Enterprise-level SMS platform customization development expert https://51smspush.com/. smspush : A customized SMS platform that can be deployed within the enterprise, with three-network coverage, not afraid of large concurrent access, and can be customized and expanded; the content of the SMS is determined by you, no longer bound, with rich interfaces, long SMS support, and optional signature. On April 8, 2020, China’s three major telecom operators jointly released the “5G Message White Paper”, and the 51 SMS platform will also be newly upgraded to the “51 Commercial Message Platform” to fully support 5G RCS messages.

The famous cloud hosting service provider DigitalOcean released the latest hosting plan. The entry-level Droplet configuration is upgraded to: 1 core CPU, 1G memory, 25G high-speed SSD, and the price is 5$/month. Friends who need to use DigitalOcean can open this link : https://ift.tt/iwNBRpl to open your DO host road.

Gopher Daily Archive Repository – https://ift.tt/9VNGUaQ

my contact information:

  • Weibo: https://ift.tt/r5Ttjyq
  • Blog: tonybai.com
  • github: https://ift.tt/NGS6apv

Business cooperation methods: writing, publishing books, training, online courses, partnership entrepreneurship, consulting, advertising cooperation.

© 2022, bigwhite . All rights reserved.

This article is reprinted from https://tonybai.com/2022/06/06/the-disappeared-method-in-method-set/
This site is for inclusion only, and the copyright belongs to the original author.

Leave a Comment