Bahasa Go boleh menggunakan penegasan jenis untuk melaksanakan jenis antara muka. Dalam Go, sama ada anda menukar satu jenis antara muka kepada jenis antara muka yang lain atau menukar antara muka kepada jenis asas yang lain, anda mesti menggunakan penegasan jenis terdapat dua jenis sintaks penukaran "pembolehubah ditukar: = pembolehubah antara muka. (jenis sasaran)" dan "Pembolehubah ditukar, ok := pembolehubah antara muka.(jenis sasaran)".
Persekitaran pengendalian tutorial ini: sistem Windows 7, GO versi 1.18, komputer Dell G3.
Di Golang, untuk menukar jenis antara muka kepada jenis antara muka lain atau untuk menukar antara muka kepada jenis asas lain, anda mesti menggunakan penegasan jenis.
Format penegasan jenis
Penegasan jenis ialah operasi yang digunakan pada nilai antara muka. Secara sintaksis ia kelihatan seperti i.(T) dipanggil jenis penegasan, di mana i mewakili jenis antara muka dan T mewakili jenis. Penegasan jenis menyemak sama ada jenis dinamik objek yang dikendalikannya sepadan dengan jenis yang ditegaskan.
Format asas penegasan jenis adalah seperti berikut:
t := i.(T)
Di mana i mewakili pembolehubah antara muka, T mewakili jenis sasaran yang ditukar, dan t mewakili pembolehubah yang ditukar.
Terdapat dua kemungkinan di sini. Pertama, jika jenis yang ditegaskan T adalah jenis konkrit, maka penegasan jenis menyemak sama ada jenis dinamik i adalah sama dengan T . Jika semakan ini berjaya, hasil penegasan jenis ialah nilai dinamik i, yang sudah tentu jenis T. Dengan kata lain, penegasan jenis untuk jenis konkrit memperoleh nilai konkrit daripada operannya. Sekiranya pemeriksaan gagal, operasi seterusnya akan menimbulkan panik. Contohnya:
var w io.Writer w = os.Stdout f := w.(*os.File) // 成功: f == os.Stdout c := w.(*bytes.Buffer) // 死机:接口保存*os.file,而不是*bytes.buffer
Kedua, jika sebaliknya jenis yang ditegaskan T ialah jenis antara muka, maka penegasan jenis menyemak sama ada jenis dinamik i memenuhi T. Jika semakan ini berjaya, nilai dinamik tidak dapat diambil; hasilnya masih merupakan nilai antara muka dengan bahagian jenis dan nilai yang sama, tetapi hasilnya mempunyai jenis T. Dalam erti kata lain, penegasan jenis pada jenis antara muka mengubah cara jenis diwakili dan mengubah set kaedah yang tersedia (biasanya lebih besar), tetapi ia melindungi bahagian jenis dan nilai dinamik nilai antara muka.
Selepas penegasan jenis pertama di bawah, kedua-dua w dan rw memegang os.Stdout supaya masing-masing mempunyai jenis dinamik *os.Fail, tetapi pembolehubah w ialah jenis io.Writer yang hanya terdedah kepada bahagian luar world Kaedah Tulis fail terdedah, tetapi pembolehubah rw hanya mendedahkan kaedah Bacanya.
var w io.Writer w = os.Stdout rw := w.(io.ReadWriter) // 成功:*os.file具有读写功能 w = new(ByteCounter) rw = w.(io.ReadWriter) // 死机:*字节计数器没有读取方法
Jika objek operasi penegasan ialah nilai antara muka sifar, maka penegasan jenis akan gagal tanpa mengira jenis yang ditegaskan. Hampir tidak ada keperluan untuk menegaskan jenis antara muka yang kurang ketat (set kaedah yang kurang) kerana ia berkelakuan seperti operasi tugasan, kecuali untuk nilai antara muka nihil.
Jika saya tidak melaksanakan sepenuhnya kaedah antara muka T, pernyataan ini akan mencetuskan ranap sistem. Mencetuskan masa henti tidak begitu mesra, jadi terdapat cara lain untuk menulis pernyataan di atas:
t,ok := i.(T)
Dengan cara ini, jika antara muka tidak dilaksanakan, ok akan ditetapkan kepada false dan t akan ditetapkan kepada taip nilai T. 0. Dalam pelaksanaan biasa, ok adalah benar. Di sini ok boleh dianggap sebagai: hasil sama ada antara muka i melaksanakan jenis T.
Tukar antara muka kepada antara muka lain
Jenis yang melaksanakan antara muka juga melaksanakan antara muka yang lain penukaran antara.
Burung dan babi mempunyai ciri yang berbeza Burung boleh terbang, babi tidak boleh terbang, tetapi kedua-dua haiwan boleh berjalan. Jika anda menggunakan struktur untuk melaksanakan burung dan babi, kaedah Fly() dan Walk() yang memberi mereka ciri tersendiri membolehkan burung dan babi melaksanakan antara muka haiwan terbang (Flyer) dan antara muka haiwan berjalan (Walker) masing-masing.
Selepas kejadian burung dan babi dicipta, ia disimpan ke dalam peta jenis antara muka{}. Jenis antara muka{} mewakili antara muka kosong, yang bermaksud bahawa antara muka ini boleh disimpan sebagai sebarang jenis. Lakukan operasi penegasan pada pembolehubah{} antara muka yang memegang contoh burung atau babi Jika objek penegasan adalah jenis yang ditentukan oleh penegasan, antara muka yang ditukar kepada jenis objek penegasan dikembalikan jika ia bukan jenis penegasan , parameter kedua penegasan akan mengembalikan palsu.
Sebagai contoh, kod berikut:
var obj interface = new(bird) f, isFlyer := obj.(Flyer)
Dalam kod, new(bird) menjana contoh burung jenis *burung, dan tika ini disimpan dalam pembolehubah obj jenis antara muka{}. Gunakan penegasan jenis obj.(Flyer) untuk menukar obj kepada antara muka Flyer. f ialah jenis antara muka Flyer apabila penukaran berjaya, isFlyer menunjukkan sama ada penukaran berjaya, dan jenisnya adalah bool.
Berikut ialah kod terperinci (kod 1):
package main import "fmt" // 定义飞行动物接口 type Flyer interface { Fly() } // 定义行走动物接口 type Walker interface { Walk() } // 定义鸟类 type bird struct { } // 实现飞行动物接口 func (b *bird) Fly() { fmt.Println("bird: fly") } // 为鸟添加Walk()方法, 实现行走动物接口 func (b *bird) Walk() { fmt.Println("bird: walk") } // 定义猪 type pig struct { } // 为猪添加Walk()方法, 实现行走动物接口 func (p *pig) Walk() { fmt.Println("pig: walk") } func main() { // 创建动物的名字到实例的映射 animals := map[string]interface{}{ "bird": new(bird), "pig": new(pig), } // 遍历映射 for name, obj := range animals { // 判断对象是否为飞行动物 f, isFlyer := obj.(Flyer) // 判断对象是否为行走动物 w, isWalker := obj.(Walker) fmt.Printf("name: %s isFlyer: %v isWalker: %v\n", name, isFlyer, isWalker) // 如果是飞行动物则调用飞行动物接口 if isFlyer { f.Fly() } // 如果是行走动物则调用行走动物接口 if isWalker { w.Walk() } } }
Penerangan kod adalah seperti berikut:
Barisan 6 mentakrifkan antara muka daripada haiwan terbang.
Baris 11 mentakrifkan antara muka haiwan berjalan.
Baris 16 dan 30 masing-masing mentakrifkan objek burung dan babi, dan masing-masing melaksanakan antara muka haiwan terbang dan haiwan berjalan.
Baris 41 ialah peta yang memetakan nama objek dan kejadian objek.
Barisan 47 mula merentasi peta, obj ialah jenis antara muka{} antara muka.
第 50 行中,使用类型断言获得 f,类型为 Flyer 及 isFlyer 的断言成功的判定。
第 52 行中,使用类型断言获得 w,类型为 Walker 及 isWalker 的断言成功的判定。
第 57 和 62 行,根据飞行动物和行走动物两者是否断言成功,调用其接口。
代码输出如下:
将接口转换为其他类型
在代码 1 中,可以实现将接口转换为普通的指针类型。例如将 Walker 接口转换为 *pig 类型,请参考下面的代码:
p1 := new(pig) var a Walker = p1 p2 := a.(*pig) fmt.Printf("p1=%p p2=%p", p1, p2)
对代码的说明如下:
第 3 行,由于 pig 实现了 Walker 接口,因此可以被隐式转换为 Walker 接口类型保存于 a 中。
第 4 行,由于 a 中保存的本来就是 *pig 本体,因此可以转换为 *pig 类型。
第 6 行,对比发现,p1 和 p2 指针是相同的。
如果尝试将上面这段代码中的 Walker 类型的 a 转换为 *bird 类型,将会发出运行时错误,请参考下面的代码:
p1 := new(pig) var a Walker = p1 p2 := a.(*bird)
运行时报错:
panic: interface conversion: main.Walker is *main.pig, not *main.bird
报错意思是:接口转换时,main.Walker 接口的内部保存的是 *main.pig,而不是 *main.bird。
因此,接口在转换为其他类型时,接口内保存的实例对应的类型指针,必须是要转换的对应的类型指针。
总结
接口和其他类型的转换可以在Go语言中自由进行,前提是已经完全实现。
接口断言类似于流程控制中的 if。但大量类型断言出现时,应使用更为高效的类型分支 switch 特性。
Atas ialah kandungan terperinci Bagaimana untuk menukar jenis antara muka bahasa go. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!