Go 学习笔记介绍 8 接口、类型断言、类型开关
介绍
这是来自 Funai Research Institute Digital 的 osw。我决定在工作中使用 Go 语言,所以我将从现在开始学习它。这是备忘录。如果您可以参考,我将不胜感激。
目标听众
- 正在学习围棋的人
- 那些已经学习过其他语言基本语法的人
学习环境
学习环境是这样的:下面这篇文章总结了这个环境的搭建备忘录。如果您有兴趣,请参考它。
- Windows 11 家庭版 / 22H2
- VSCode/1.72.2
- go 版本 go1.19.2 windows/amd64
- git 版本 2.38.0.windows.1
以前的学习
上次我们学习了方法。
界面
似乎 Java 和 C++ 准备作为抽象实现和实现多态性的一种手段。至于如何使用,定义一个只收集没有定义的函数声明的接口,在Java中称为抽象方法,在C++中称为纯虚函数,通过“实现”它来使用。
但是,我不太明白措辞,但显然,在 Go 中实现接口意味着将接口中声明的函数定义为方法,并通过将其与接收者链接来“实现”接口。似乎表达看起来图像如下。
- 定义接口
- 实现接口的功能
- 将接收器绑定到实现的函数并使其成为方法
- 附加到方法的接收器“实现”接口
如果将语法用户类型绑定为接收者,则该用户类型将实现一个接口。 Java 中没有关键字“implements”。
句法
// ユーザ型の定義 type ユーザ型名 型 // インタフェース定義 type インタフェース名 interface { メソッド名 } // メソッドの実装 func (レシーバ 型) メソッド名() { // 処理 }
示例代码
package main import "fmt" // ユーザ型の定義 type AmericanShorthair int type Munchkin int // にゃーインタフェース定義 type IMeow interface { Meow() } // アメショの実装 // この時点でAmericanShorthair型はIMeowインタフェースを実装している func (cat AmericanShorthair) Meow() { fmt.Println("にゃー") } // マンチカンの実装 // この時点でMunchkin型はIMeowインタフェースを実装している func (cat Munchkin) Meow() { fmt.Println("なおーん") } func main() { // インタフェース型変数にそれぞれ格納 // 格納される要素それぞれの型はインタフェースを実装済みなので代入できる cats := []IMeow{ AmericanShorthair(0), Munchkin(0), } for _, cat := range cats { cat.Meow() } }
执行结果
にゃー なおーん
空接口
它是一种可以接收任何东西的类型。但是,界面似乎是相同的。接口类型变量不能分配给任何不实现接口的东西,所以似乎所有类型都实现了空接口,因为空接口可以接收任何东西。
句法
var v interface{}
示例代码
package main import "fmt" func main() { var v interface{} v = 1 fmt.Println(v) v = "test" fmt.Println(v) v = [...]int{0, 1, 2, 3, 4} fmt.Println(v) v = []int{0, 1, 2, 3, 4} fmt.Println(v) v = map[int]string { 0: "abc", 1: "def", } fmt.Println(v) }
执行结果
1 test [0 1 2 3 4] [0 1 2 3 4] map[0:abc 1:def]
类型断言
空接口可以接收任何值,但似乎不再看到原始类型信息,无法访问它拥有的字段和值。因此,有一种方法可以将接口类型中接收到的值强制转换为任何类型,并且似乎是一种类型断言。
句法
// 変換できればokにtrue、valueにその値が返る。できなければfalse, ゼロ値が返る value, ok := インタフェース型変数.(任意の型)
示例代码
package main import "fmt" type Person struct { Name string Age int } func main() { var i interface{} /* * アクセスできないことの確認 */ fmt.Println("構造体で中身にアクセスできるか確認") i = Person{ "tanaka", 99, } fmt.Println(i) // fmt.Println(i.Name) i.Name undefined (type interface{} has no field or method Name) // fmt.Println(i.Age) i.Age undefined (type interface{} has no field or method Age) fmt.Println(" 配列で中身にアクセスできるか確認") i = [...]int{0, 1, 2, 3, 4} fmt.Println(i) // fmt.Println(i[0]) invalid operation: cannot index i (variable of type interface{}) fmt.Println(" スライスで中身にアクセスできるか確認") i = []int{0, 1, 2, 3, 4} fmt.Println(i) // fmt.Println(i[0]) invalid operation: cannot index i (variable of type interface{}) fmt.Println(" マップで中身にアクセスできるか確認") i = map[int]string{ 0: "abc", 1: "def", } fmt.Println(i) // fmt.Println(i[0]) invalid operation: cannot index i (variable of type interface{}) /* * 型アサーションでアクセスできることの確認 */ fmt.Println(" 構造体にキャストし、中身にアクセスできるか確認") i = Person{ "tanaka", 99, } person, ok := i.(Person) if ok { fmt.Println("person.Name:", person.Name) } fmt.Println(" 配列にキャストし、中身にアクセスできるか確認") i = [...]int{0, 1, 2, 3, 4} array, ok := i.([5]int) if ok { fmt.Println("array[4]:", array[4]) } fmt.Println(" スライスにキャストし、中身にアクセスできるか確認") i = []int{0, 1, 2, 3, 4} slice, ok := i.([]int) if ok { fmt.Println("slice[4]:", slice[4]) } fmt.Println(" マップにキャストし、中身にアクセスできるか確認") i = map[int]string{ 0: "abc", 1: "def", } mp, ok := i.(map[int]string) if ok { fmt.Println("mp[0]:", mp[0]) } /* * 型アサーションでわざとキャストを失敗させる */ fmt.Println(" 構造体 -> intにキャストし、戻り値を確認する") i = Person{ "tanaka", 99, } p, ok := i.(int) if ok { fmt.Println("person.Name:", person.Name) } else { fmt.Println("キャストに失敗しました p:", p) } fmt.Println(" 配列 -> intにキャストし、戻り値を確認する") i = [...]int{0, 1, 2, 3, 4} a, ok := i.(int) if ok { fmt.Println("array[4]:", array[4]) } else { fmt.Println("キャストに失敗しました a:", a) } fmt.Println(" スライス -> intにキャストし、戻り値を確認する") i = []int{0, 1, 2, 3, 4} s, ok := i.(int) if ok { fmt.Println("slice[4]:", slice[4]) } else { fmt.Println("キャストに失敗しました s:", s) } fmt.Println(" マップ -> intにキャストし、戻り値を確認する") i = map[int]string{ 0: "abc", 1: "def", } m, ok := i.(int) if ok { fmt.Println("mp[0]:", mp[0]) } else { fmt.Println("キャストに失敗しました m:", m) } }
执行结果
構造体で中身にアクセスできるか確認 {tanaka 99} 配列で中身にアクセスできるか確認 [0 1 2 3 4] スライスで中身にアクセスできるか確認 [0 1 2 3 4] マップで中身にアクセスできるか確認 map[0:abc 1:def] 構造体にキャストし、中身にアクセスできるか確認 person.Name: tanaka 配列にキャストし、中身にアクセスできるか確認 array[4]: 4 スライスにキャストし、中身にアクセスできるか確認 slice[4]: 4 マップにキャストし、中身にアクセスできるか確認 mp[0]: abc 構造体 -> intにキャストし、戻り値を確認する キャストに失敗しました p: 0 配列 -> intにキャストし、戻り値を確認する キャストに失敗しました a: 0 スライス -> intにキャストし、戻り値を確認する キャストに失敗しました s: 0 マップ -> intにキャストし、戻り値を確認する キャストに失敗しました m: 0
类型开关
与普通开关不同,它通过指定大小写类型进行分支。要评估的表达式就像接口类型变量的“原始类型”。类型是通过接口类型变量 .(type) 获得的。
句法
// 戻り値はinterface{}型ではなく、もともとの型に合った値が返る switch value := i.(type) { case int: fmt.Println("iはint型です 値:", value) case string: fmt.Println("iはstring型です 値:", value) default: fmt.Println("iはそれ以外です") }
示例代码
package main import "fmt" type Person struct { Name string } func main() { var i interface{} = Person{"tanaka"} switch value := i.(type) { case int: fmt.Println("iはint型です 値:", value) case string: fmt.Println("iはstring型です 値:", value) case Person: // 返ってきたvalueはフィールドにアクセスできるためPerson型。interface{}型ではない fmt.Println("iはPerson型です 値:", value.Name) default: fmt.Println("iはそれ以外です 値:", value) } }
执行结果
iはPerson型です 値: tanaka
综上所述
目前为止就这样了。
原创声明:本文系作者授权爱码网发表,未经许可,不得转载;
原文地址:https://www.likecs.com/show-308630726.html
- 上一篇 »PHP学习笔记
- 下一篇 »【Python】学习笔记2-数组类型:字符串方法、字典、元组