インターフェース
ではGolang
世界では、と呼ばれるものがあるinterface
何かが、それは素晴らしいです、。
まず、データ型インターフェイス{}
変数が整数であるか文字列であるかにかかわらず、変数のデータ型が以前はわからないが、それでも使用したい場合。
Golang
「名前」と呼ばれるinterface{}
データ型が生成され、それがどの型であるかが不明であることを示します。例:
package main
import (
"fmt"
"reflect"
)
func print(i interface{}) {
fmt.Println(i)
}
func main() {
// 声明一个未知类型的 a,表明不知道是什么类型
var a interface{}
a = 2
fmt.Printf("%T,%v\n", a, a)
// 传入函数
print(a)
print(3)
print("i love you")
// 使用断言,判断是否是 int 数据类型
v, ok := a.(int)
if ok {
fmt.Printf("a is int type,value is %d\n", v)
}
// 使用断言,判断变量类型
switch a.(type) {
case int:
fmt.Println("a is type int")
case string:
fmt.Println("a is type string")
default:
fmt.Println("a not type found type")
}
// 使用反射找出变量类型
t := reflect.TypeOf(a)
fmt.Printf("a is type: %s", t.Name())
}
出力:
int,2
2
3
i love you
a is int type,value is 2
a is type int
a is type: int
1.1。基本的な使用法
interface{}
未知の型の変数を宣言するために使用しますa
:
// 声明一个未知类型的 a,表明不知道是什么类型
var a interface{}
a = 2
fmt.Printf("%T,%v\n", a, a)
次に、変数に整数を割り当てます。a=2
現時点a
では、それはまだ不明なタイプです。プレースホルダー%T
を使用して変数の実際のタイプを出力し、プレースホルダーを使用し%v
て値を出力します。このときfmt.Printf
、タイプは内部的に判断されます。
関数のパラメーターをinterface
変数の定義と同じように設定することもできます。
func print(i interface{}) {
fmt.Println(i)
}
使用する場合:
// 传入函数
print(a)
print(3)
print("i love you")
print
関数に渡すパラメーターは、整数3
や文字列など、任意の型にすることができますi love you
。関数を入力すると、関数内の変数はi
型を失い、不明な型になります。この機能により、異なるタイプのデータを処理する場合に複数の関数を記述する必要がなくなります。
もちろん、構造内のフィールドも次のようになりますinterface{}
。
type H struct {
A interface{}
B interface{}
}
1.2。特定のタイプを決定する
定義しましたinterface{}
が、実際の使用にあたっては、タイプを判断する必要があります。判断には2つの方法があります。
アサーションを使用:
// 使用断言,判断是否是 int 数据类型
v, ok := a.(int)
if ok {
fmt.Printf("a is int type,value is %d\n", v)
}
変数の直後に使用すると.(int)
、2つの戻り値v, ok
が返されます。それが本当に整数型であるok
ことをtrue
示している場合、この整数が割り当てられv
、私たちはv
楽しく遊ぶことができます。それ以外の場合は、ok
のようにfalse
、v
0のデフォルト値であるNULL値に。
我々はすべてのケースで使用する場合は、ので、厳しいものにinterface{}
変数の型、データ型があるかもしれない.(int)
、かもしれない.(string)
、使用することができますswitch
簡単にするために:
// 使用断言,判断变量类型
switch a.(type) {
case int:
fmt.Println("a is type int")
case string:
fmt.Println("a is type string")
default:
fmt.Println("a not type found type")
}
ではではswicth
、アサーションは、もはや使用されていない.(具体类型)
、しかしa.(type)
。
最後に、リフレクションパッケージreflect
を使用してデータ型を決定する方法があります。
// 使用反射找出变量类型
t := reflect.TypeOf(a)
fmt.Printf("a is type: %s", t.Name())
このパッケージは、非セキュアポインターを直接使用して、実際のデータ型を取得します。
func TypeOf(i interface{}) Type {
eface := *(*emptyInterface)(unsafe.Pointer(&i))
return toType(eface.typ)
}
一般的な日常の開発では、リフレクションパッケージはほとんど使用されません。
2.インターフェース構造
私たちはみな関数型プログラミングか構造型メソッドプログラミングですが、他の言語に特徴的なオブジェクト指向、オブジェクト継承はありませんか?はい、Golang
言語はインターフェイス指向プログラミングと呼ばれています。
package main
import (
"fmt"
"reflect"
)
// 定义一个接口,有一个方法
type A interface {
Println()
}
// 定义一个接口,有两个方法
type B interface {
Println()
Printf() int
}
// 定义一个结构体
type A1Instance struct {
Data string
}
// 结构体实现了Println()方法,现在它是一个 A 接口
func (a1 *A1Instance) Println() {
fmt.Println("a1:", a1.Data)
}
// 定义一个结构体
type A2Instance struct {
Data string
}
// 结构体实现了Println()方法,现在它是一个 A 接口
func (a2 *A2Instance) Println() {
fmt.Println("a2:", a2.Data)
}
// 结构体实现了Printf()方法,现在它是一个 B 接口,它既是 A 又是 B 接口
func (a2 *A2Instance) Printf() int {
fmt.Println("a2:", a2.Data)
return 0
}
func main() {
// 定义一个A接口类型的变量
var a A
// 将具体的结构体赋予该变量
a = &A1Instance{Data: "i love you"}
// 调用接口的方法
a.Println()
// 断言类型
if v, ok := a.(*A1Instance); ok {
fmt.Println(v)
} else {
fmt.Println("not a A1")
}
fmt.Println(reflect.TypeOf(a).String())
// 将具体的结构体赋予该变量
a = &A2Instance{Data: "i love you"}
// 调用接口的方法
a.Println()
// 断言类型
if v, ok := a.(*A1Instance); ok {
fmt.Println(v)
} else {
fmt.Println("not a A1")
}
fmt.Println(reflect.TypeOf(a).String())
// 定义一个B接口类型的变量
var b B
//b = &A1Instance{Data: "i love you"} // 不是 B 类型
b = &A2Instance{Data: "i love you"}
fmt.Println(b.Printf())
}
出力:
a1: i love you
&{i love you}
*main.A1Instance
a2: i love you
not a A1
*main.A2Instance
a2: i love you
0
インターフェイスタイプを定義できます。使用するtype 接口名 interface
と、今回は次のようになりませんinterface{}
。
// 定义一个接口,有一个方法
type A interface {
Println()
}
// 定义一个接口,有两个方法
type B interface {
Println()
Printf() int
}
これは、インターフェースことが分かるA
とB
限り構造がされると、各インターフェイスが多数の方法を有し、抽象的構造であるstruct
これらのメソッドを実装し、これらは、インターフェースのこのタイプの構造です。など:
// 定义一个结构体
type A1Instance struct {
Data string
}
// 结构体实现了Println()方法,现在它是一个 A 接口
func (a1 *A1Instance) Println() {
fmt.Println("a1:", a1.Data)
}
// 定义一个结构体
type A2Instance struct {
Data string
}
// 结构体实现了Println()方法,现在它是一个 A 接口
func (a2 *A2Instance) Println() {
fmt.Println("a2:", a2.Data)
}
// 结构体实现了Printf()方法,现在它是一个 B 接口,它既是 A 又是 B 接口
func (a2 *A2Instance) Printf() int {
fmt.Println("a2:", a2.Data)
return 0
}
構造体に特定のメソッドを実装する必要があるため、インターフェース型の変数を定義して、それに構造体を割り当てることができます。
// 定义一个A接口类型的变量
var a A
// 将具体的结构体赋予该变量
a = &A1Instance{Data: "i love you"}
// 调用接口的方法
a.Println()
構造がこのメソッドを実装していない場合、コンパイルは失敗し、バイナリはコンパイルできません。
もちろん、アサーションとリフレクションを使用して、インターフェイスタイプが属する実際の構造を判別することもできますstruct
。
// 断言类型
if v, ok := a.(*A1Instance); ok {
fmt.Println(v)
} else {
fmt.Println("not a A1")
}
fmt.Println(reflect.TypeOf(a).String())
Golang
構造体がインターフェイスメソッドを実装しているかどうかを判断するのは非常に賢明です。実装されている場合、構造体はインターフェイスタイプです。インターフェース構造の特徴を柔軟に活かし、組み合わせた形でより柔軟なプログラムを開発します。
シリーズ記事エントリー
私は、スター陳思い、私が個人的に書かれているようこそ(Golangが達成)のデータ構造とアルゴリズムの記事で始まる、より親しみやすいGitBookを読むために。
- データ構造とアルゴリズム(Golang実装)(1)Golang-Prefaceの簡単な紹介
- データ構造とアルゴリズム(Golang実装)(2)Golangパッケージ、変数、関数の簡単な紹介
- データ構造とアルゴリズム(Golang実装)(3)Golangフロー制御ステートメントの簡単な紹介
- データ構造とアルゴリズム(Golang実装)(4)Golang構造とメソッドの簡単な紹介
- データ構造とアルゴリズム(Golang実装)(5)Golangインターフェースの簡単な紹介
- データ構造とアルゴリズム(Golang実装)(6)Golang並行性、コルーチン、チャネルの簡単な紹介
- データ構造とアルゴリズム(Golang実装)(7)Golang標準ライブラリの簡単な紹介
- データ構造とアルゴリズム(Golang実装)(8.1)基本的な知識-序文
- データ構造とアルゴリズム(Golang実装)(8.2)基本的な知識-分割と征服と再帰
- データ構造とアルゴリズム(Golang実装)(9)基本的な知識アルゴリズムの複雑さとプログレッシブシンボル
- データ構造とアルゴリズム(Golang実装)(10)基本知識-アルゴリズムの複雑さの主な方法
- データ構造とアルゴリズム(Golang実装)(11)一般的なデータ構造-序文
- データ構造とアルゴリズム(Golang実装)(12)一般的なデータ構造にリンクされたリスト
- データ構造とアルゴリズム(Golang実装)(13)一般的なデータ構造-可変長配列
- データ構造とアルゴリズム(Golang実装)(14)一般的なデータ構造-スタックとキュー
- データ構造とアルゴリズム(Golang実装)(15)一般的なデータ構造-リスト
- データ構造とアルゴリズム(Golang実装)(16)一般的なデータ構造-辞書
- データ構造とアルゴリズム(Golang実装)(17)一般的なデータ構造ツリー
- データ構造とアルゴリズム(Golang実装)(18)ソートアルゴリズム-序文
- データ構造とアルゴリズム(Golang実装)(19)ソートアルゴリズム-バブルソート
- データ構造とアルゴリズム(Golang実装)(20)ソートアルゴリズム選択ソート
- データ構造とアルゴリズム(Golang実装)(21)ソートアルゴリズム挿入ソート
- データ構造とアルゴリズム(Golang実装)(22)ソートアルゴリズム-ヒルソート
- データ構造とアルゴリズム(Golang実装)(23)ソートアルゴリズム-マージソート
- データ構造とアルゴリズム(Golang実装)(24)ソートアルゴリズム-優先度キューとヒープソート
- データ構造とアルゴリズム(Golang実装)(25)ソートアルゴリズム-迅速なソート
- データ構造とアルゴリズム(Golang実装)(26)ルックアップアルゴリズム-ハッシュテーブル
- データ構造とアルゴリズム(Golang実装)(27)検索アルゴリズム-バイナリ検索ツリー
- データ構造とアルゴリズム(Golang実装)(28)検索アルゴリズム-AVLツリー
- データ構造とアルゴリズム(Golang実装)(29)検索アルゴリズム-2-3ツリーと左寄りの赤黒ツリー
- データ構造とアルゴリズム(Golangによって実装)(30)検索アルゴリズム-2-3-4ツリーと通常の赤黒ツリー