golang では、インターフェースはメソッドをまとめるために使用される型であり、その機能は次のとおりです: 1. オブジェクト指向設計のためのメソッドのラッパーとして; 2. さまざまなメソッドとして関数パラメータなどを受け取るために使用されます。インターフェースの定義構文は「type インターフェース タイプ名 インターフェース{メソッド名(パラメータリスト1) 戻り値リスト}」となり、メソッド名の頭文字が大文字、インターフェースタイプ名の頭文字も大文字の場合、このメソッドは、インターフェイスが配置されているパッケージ (パッケージ) の外部のコード アクセスで使用できます。
このチュートリアルの動作環境: Windows 7 システム、GO バージョン 1.18、Dell G3 コンピューター。
1. インターフェイスとは何ですか?
インターフェイスはメソッド シグネチャの組み合わせであり、オブジェクトの一連の動作を定義するためにインターフェイスを使用します。
(メソッドと通常の関数の違いに注意してください)
インターフェースは型であり、通常の言語のインターフェースとは異なります。メソッドのパックです。ただし、GO 言語に関数ベースのオブジェクト指向を持たせるのは、この種の収束です。
インターフェイスの主な機能:
1. オブジェクト指向設計のメソッド コレクターとして。
2. さまざまなデータのベアラーとして、関数パラメータの受信などに使用できます。
これも同様で、GO 言語は インターフェイス指向プログラミング を提唱しています。
2. インターフェースの定義を使用します
2.1 定義
同様の構造
type 接口类型名 interface{ 方法名1( 参数列表1 ) 返回值列表1 方法名2( 参数列表2 ) 返回值列表2 … }
もちろん、これはメソッドを使用したインターフェイス定義にすぎず、データ指向のインターフェイスではありません。
インターフェイス名: type を使用してインターフェイスをカスタム タイプ名として定義します。 Go 言語のインターフェイスに名前を付ける場合、通常、単語の後に er が追加されます。たとえば、書き込み操作を含むインターフェイスは Writer と呼ばれ、文字列関数を含むインターフェイスは Stringer と呼ばれます。 ##。 #待って。インターフェイス名は、インターフェイスの型の意味を強調するのが最適です。
- メソッド名: メソッド名の最初の文字が大文字で、インターフェイス型名の最初の文字も大文字の場合、このメソッドにはパッケージ外のコードからアクセスできます。インターフェイスが配置されています。 #パラメータリスト、戻り値リスト:パラメータリスト、戻り値リスト内のパラメータ変数名は省略可能です。
を使用する オブジェクトがインターフェース内のすべてのメソッドを実装している限り、オブジェクトはインターフェースを実装します。つまり、インターフェイス
は、実装する必要があるメソッド のリストです。 //定义接口
type FastfoodStore interface{
MakeHamberger()
MakeFriedChips()
MakeSoftDrink()
}
//定义结构体
type KFC struct{}
type HambergerKing struct{}
//实现了接口中所有的方法
func (kfc KFC) MakeHamberger(){
fmt.println("肯德基的汉堡")
}
func (kfc KFC) MakeFriedChips(){
fmt.println("肯德基的薯条")
}
func (kfc KFC) MakeSoftDrink(){
fmt.println("肯德基的饮料")
}
func (K *HambergerKing) MakeHameberger(){
fmt.println("汉堡王的汉堡")
}
func (K *HambergerKing) MakeFriedChips(){
fmt.println("汉堡王的薯条")
}
func (K *HambergerKing) MakeSoftDrink(){
fmt.println("汉堡王的饮料")
}
Java のインターフェイスの明示的な実装とは異なり、Go 言語は暗黙的に実装されていることがわかります。
Java の場合: インターフェイスを実装するには、インターフェイスを明示的に宣言し、すべてのメソッドを実装する必要があります。
- Go の場合: インターフェイスを実装するすべてのメソッドは、暗黙的にインターフェイスを実装します。
- #それでは、GO 言語は型がインターフェイスであるかどうかをどのようにチェックするのでしょうか?
回答: Go 言語は、パラメーターを渡すとき、パラメーターを返すとき、および変数の割り当てを行うときに、型がインターフェイスを実装しているかどうかのみをチェックします。型チェック プロセスの観点から見ると、コンパイラは必要な場合にのみ型をチェックします。型がインターフェイスを実装する場合、インターフェイス内のすべてのメソッドを実装するだけでよく、プログラミング言語のように明示的に宣言する必要はありません。 Javaなど。
上記のインターフェイスを実装すると、KFC は構造体オブジェクトを使用して実装され、ハンバーガー キングはポインターを使用して実装されることがわかります。この 2 つの違いは何ですか?
答え: 違いは、インターフェイスを初期化するときです。//结构体初始化和指针初始化
var f faststore = KFC{} //可以通过编译
var f faststore = &KFC{} //可以通过编译
var f faststore = HambergerKing{} //无法通过编译
var f faststore = &HambergerKing{} //可以通过编译
では、ポインターを使用して構造体を実装および初期化すると、なぜ機能しないのでしょうか?
回答:
Go 言語はパラメータを渡すときに値を使用します。#上の図に示すように、上記のコードで初期化された変数ポインターや構造体に関係なく、メソッドの呼び出し時に値のコピーが発生します。
如上图左侧,对于 &HambergerKing{} 来说,这意味着拷贝一个新的 &HambergerKing{} 指针,这个指针与原来的指针指向一个相同并且唯一的结构体,所以编译器可以隐式的对变量解引用(dereference)获取指针指向的结构体;
如上图右侧,对于 HambergerKing{} 来说,这意味着方法会接受一个全新的 HambergerKing{},因为方法的参数是*HambergerKing,编译器不会无中生有创建一个新的指针;即使编译器可以创建新指针,这个指针指向的也不是最初调用该方法的结构体;
上面的分析解释了指针类型的现象,当我们使用指针实现接口时,只有指针类型的变量才会实现该接口;当我们使用结构体实现接口时,指针类型和结构体类型都会实现该接口。当然这并不意味着我们应该一律使用结构体实现接口,这个问题在实际工程中也没那么重要,在这里我们只想解释现象背后的原因。
在上面我们说过,interface有两种用法,现在介绍了其中一种就是作为方法的收束器。那么第二种就是作为数据的承载者。
2.3 数据承载者
作为数据容器时,接口就是一个“空”接口,这个空来形容没有Method。空interface(interface{})不包含任何的method,正因为如此,所有的类型都实现了空interface。空interface对于描述起不到任何的作用(因为它不包含任何的method),但是空interface在我们需要存储任意类型的数值的时候相当有用,因为它可以存储任意类型的数值。它有点类似于C语言的void*类型。
需要注意的是,与 C 语言中的 void * 不同,interface{} 类型不是任意类型。如果我们将类型转换成了 interface{} 类型,变量在运行期间的类型也会发生变化,获取变量类型时会得到 interface{}。
我们尝试从底层实现来解释两种用法的不同,你会好理解一些。Go 语言使用 runtime.iface 表示第一种接口,使用 runtime.eface 表示第二种不包含任何方法的接口 interface{},两种接口虽然都使用 interface 声明,但是由于后者在 Go 语言中很常见,所以在实现时使用了特殊的类型。
空接口作为函数的参数
使用空接口实现可以接收任意类型的函数参数。
// 空接口作为函数参数 func show(a interface{}) { fmt.Printf("type:%T value:%v\n", a, a) }
空接口作为map的值
使用空接口实现可以保存任意值的字典。
// 空接口作为map值 var studentInfo = make(map[string]interface{}) studentInfo["name"] = "Wilen" studentInfo["age"] = 18 studentInfo["married"] = false fmt.Println(studentInfo) //gin框架的gin.H{}
三、关于接口类型转换
interface 可以存储所有的值,那么自然会涉及到类型转换这个话题。与此同时,我们也将在这节细说类型转换中,因为结构体实现和结构体指针实现的接口的异同。
3.1结构体指针实现接口
//我们仍然运用上面快餐店的例子 type Store interface{ MakeHamberger() } type KFC struct{ name string } func (k *KFC) MakeHamberger(){ fmt.println(k.name+"制作了一个汉堡") } func main(){ var s store = &KFC{name:"东街店"} store.MakeHamberger() }
这里将上述代码生成的汇编指令拆分成三部分分析:
1.结构体 KFC 的初始化;
KFC的初始化又可以分为下面几步:
获取 KFC 结构体类型指针并将其作为参数放到栈上;
通过 CALL 指定调用 runtime.newobject函数,这个函数会以 KFC 结构体类型指针作为入参,分配一片新的内存空间并将指向这片内存空间的指针返回到 SP+8 上;
SP+8 现在存储了一个指向 KFC 结构体的指针,我们将栈上的指针拷贝到寄存器 DI 上方便操作;
由于 Cat 中只包含一个字符串类型的 Name 变量,所以在这里会分别将字符串地址 &"东街店" 和字符串长度 6 设置到结构体上。
2.赋值触发的类型转换过程;
因为 KFC 结构体的定义中只包含一个字符串,而字符串在 Go 语言中总共占 16 字节,所以每一个 KFC 结构体的大小都是 16 字节。初始化 KFC 结构体之后就进入了将 *KFC 转换成 Store 类型的过程了:
类型转换的过程比较简单,Store 作为一个包含方法的接口,它在底层使用 [runtime.iface] 结构体表示。runtime.iface 结构体包含两个字段,其中一个是指向数据的指针,另一个是表示接口和结构体关系的 tab 字段,我们已经通过上一段代码 SP+8 初始化了 KFC 结构体指针,这段代码只是将编译期间生成的 runtime.itab 结构体指针复制到 SP 上:
到这里,我们会发现 SP ~ SP+16 共同组成了 runtime.iface 结构体。
3.调用接口的方法 Quack();
栈上的这个 runtime.iface 也是 MakeHamberger() 方法的第一个入参。通过CALL()完成方法的调用。
3.2 结构体实现接口
//我们仍然运用上面快餐店的例子 type Store interface{ MakeHamberger() } type KFC struct{ name string } func (k KFC) MakeHamberger(){ fmt.println(k.name+"制作了一个汉堡") } func main(){ var s store = KFC{name:"东街店"} store.MakeHamberger() }
如果我们在初始化变量时使用指针类型 &KFC{Name: "东街店"} 也能够通过编译,不过生成的汇编代码和上一节中的几乎完全相同,所以这里也就不分析这个情况了。
初始化 KFC 结构体;
在栈上初始化 KFC 结构体,而上一节的代码在堆上申请了 16 字节的内存空间,栈上只有一个指向 KFC 的指针。
完成从 KFC 到 Store 接口的类型转换;
初始化结构体后会进入类型转换的阶段,编译器会将 go.itab."".KFC,"".Store 的地址和指向 KFC 结构体的指针作为参数一并传入 runtime.convT2I 函数:这个函数会获取 runtime.itab 中存储的类型,根据类型的大小申请一片内存空间并将 elem 指针中的内容拷贝到目标的内存中:
func convT2I(tab *itab, elem unsafe.Pointer) (i iface) { t := tab._type x := mallocgc(t.size, t, true) typedmemmove(t, x, elem) i.tab = tab i.data = x return }
runtime.convT2I 会返回一个 runtime.iface,其中包含 runtime.itab 指针和 KFC 变量。当前函数返回之后,main 函数的栈上会包含以下数据:
SP 和 SP+8 中存储的 runtime.itab 和 KFC 指针是 runtime.convT2I 函数的入参,这个函数的返回值位于 SP+16,是一个占 16 字节内存空间的 runtime.iface 结构体,SP+32 存储的是在栈上的 KFC 结构体,它会在 runtime.convT2I 执行的过程中拷贝到堆上。
3.3类型断言
如何将一个接口类型转换成具体类型?
x.(T)
非空接口
func main() { var c Store = &KFC{Name: "东街店"} switch c.(type) { case *KFC: kfc := c.(*KFC) kfc.MakeHamberger() } }
因为 Go 语言的编译器做了一些优化,所以代码中没有runtime.iface 的构建过程,不过对于这一节要介绍的类型断言和转换没有太多的影响。
switch语句生成的汇编指令会将目标类型的 hash 与接口变量中的 itab.hash 进行比较
空接口
func main() { var c interface{} = &KFC{Name: "东街店"} switch c.(type) { case *KFC: kfc := c.(*KFC) kfc.MakeHamberger() } }
上述代码会在类型断言时就不是直接获取变量中具体类型的 runtime._type,而是从 eface._type 中获取,汇编指令仍然会使用目标类型的 hash 与变量的类型比较.
以上がgolang のインターフェースは何に役立ちますか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

goisidealforbuildingscalablessystemsduetoitssimplicity、効率性、およびビルド・インコンカレンシsupport.1)

intionSingOrunautomaticallyは()andareuseforstingupenments andinitializingvariables.usemforsimpletasks、回避効果を回避し、測定可能性を測定することを検討します。

goinitializeSpackages intheordertheyareimport extionsitions withinitionsiteintheirdefinition ordord、およびfilenamesdetermineTheOordCrossMultiplefiles.thisprocesccanbeandeanded by -dependenciessedieSiesは、このマイレアドカンフレシニティン化の対象となります

custominterfacesingoarecrucialforwritingfficable、maintable、andtatablecode.theyeNabledeveloveerStofofofovioroverimplementation、拡張、methodsodsignaturesthattypespessmustimment、interfaceforoderueusavelya

シミュレーションとテストにインターフェイスを使用する理由は、インターフェイスにより、実装を指定せずに契約の定義を可能にし、テストをより孤立し、メンテナンスしやすくするためです。 1)インターフェイスの暗黙的な実装により、モックオブジェクトを簡単に作成できます。これにより、テストの実際の実装を置き換えることができます。 2)インターフェイスを使用すると、ユニットテストでのサービスの実際の実装を簡単に置き換えることができ、テストの複雑さと時間を短縮できます。 3)インターフェイスによって提供される柔軟性により、さまざまなテストケースのシミュレートされた動作の変更が可能になります。 4)インターフェイスは、テスト可能なコードを最初から設計し、コードのモジュール性と保守性を向上させるのに役立ちます。

Goでは、init関数はパッケージの初期化に使用されます。 1)init関数は、パッケージの初期化時に自動的に呼び出され、グローバル変数の初期化、接続の設定、構成ファイルの読み込みに適しています。 2)ファイルの順序で実行できる複数のinit関数がある場合があります。 3)それを使用する場合、実行順序、テストの難易度、パフォーマンスへの影響を考慮する必要があります。 4)副作用を減らし、依存関係の注入を使用し、初期化を遅延させることをお勧めします。

go'sselectStatementStreamLinesConcurrentProgrambyMultipLexIngoperations.1)Itallow swaitingonMultipleChanneloperations、実行、exectingThefirstreadyone.2)

コンテキストアンドウェイトグループは、フォーマネングに焦点を合わせており、contextAllowsingSignalingCancellationAndDeadlinesAcrossapiboundariesを採用し、GoroutinesscanSclacefly.2)WaitGroupssynchronizeGoroutines、Allcompletebebroproproproproproproprotinesを保証します


ホットAIツール

Undresser.AI Undress
リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover
写真から衣服を削除するオンライン AI ツール。

Undress AI Tool
脱衣画像を無料で

Clothoff.io
AI衣類リムーバー

Video Face Swap
完全無料の AI 顔交換ツールを使用して、あらゆるビデオの顔を簡単に交換できます。

人気の記事

ホットツール

SecLists
SecLists は、セキュリティ テスターの究極の相棒です。これは、セキュリティ評価中に頻繁に使用されるさまざまな種類のリストを 1 か所にまとめたものです。 SecLists は、セキュリティ テスターが必要とする可能性のあるすべてのリストを便利に提供することで、セキュリティ テストをより効率的かつ生産的にするのに役立ちます。リストの種類には、ユーザー名、パスワード、URL、ファジング ペイロード、機密データ パターン、Web シェルなどが含まれます。テスターはこのリポジトリを新しいテスト マシンにプルするだけで、必要なあらゆる種類のリストにアクセスできるようになります。

mPDF
mPDF は、UTF-8 でエンコードされた HTML から PDF ファイルを生成できる PHP ライブラリです。オリジナルの作者である Ian Back は、Web サイトから「オンザフライ」で PDF ファイルを出力し、さまざまな言語を処理するために mPDF を作成しました。 HTML2FPDF などのオリジナルのスクリプトよりも遅く、Unicode フォントを使用すると生成されるファイルが大きくなりますが、CSS スタイルなどをサポートし、多くの機能強化が施されています。 RTL (アラビア語とヘブライ語) や CJK (中国語、日本語、韓国語) を含むほぼすべての言語をサポートします。ネストされたブロックレベル要素 (P、DIV など) をサポートします。

SublimeText3 Linux 新バージョン
SublimeText3 Linux 最新バージョン

メモ帳++7.3.1
使いやすく無料のコードエディター

DVWA
Damn Vulnerable Web App (DVWA) は、非常に脆弱な PHP/MySQL Web アプリケーションです。その主な目的は、セキュリティ専門家が法的環境でスキルとツールをテストするのに役立ち、Web 開発者が Web アプリケーションを保護するプロセスをより深く理解できるようにし、教師/生徒が教室環境で Web アプリケーションを教え/学習できるようにすることです。安全。 DVWA の目標は、シンプルでわかりやすいインターフェイスを通じて、さまざまな難易度で最も一般的な Web 脆弱性のいくつかを実践することです。このソフトウェアは、

ホットトピック









