違い: 1. 関数は独立した関数を持つコードの一部であり、コードを再利用するために何度も繰り返し呼び出すことができますが、メソッドはクラスの動作関数であり、そのクラスのオブジェクトによってのみ呼び出すことができます。クラス。 。 2. メソッドにはレシーバーがありますが、関数にはレシーバーがありません。 3. 関数には同じ名前を付けることはできませんが、メソッドには同じ名前を付けることができます。 4. 呼び出し方法が異なります。 5. メソッドはその型を指定する必要があります。関数は汎用型ですが、構造体またはカスタム型を指定できます。 6. 関数の形式とパラメータの型は一貫している必要があり、メソッドは変更できます。
このチュートリアルの動作環境: Windows 7 システム、GO バージョン 1.18、Dell G3 コンピューター。
Go 言語では、関数とメソッドは異なり、概念的に明確な区別があります。 Java など他の言語では、一般に関数はメソッド、メソッドは関数となりますが、Go 言語では関数は構造や型に属さないメソッドを指します。 , 関数にはレシーバーがありません; メソッドにはレシーバーがあります ここで話しているメソッドは、構造体に属しているか、新しく定義された型に属しているかのいずれかです。
関数とメソッドは、概念は異なりますが、定義は非常に似ています。関数定義ステートメントにはレシーバーがないため、ステートメントを go ファイル内および go パッケージ内で直接定義できます。
func main() { sum := add(1, 2) fmt.Println(sum) } func add(a, b int) int { return a + b }
この例では、add
を関数として定義しました。その関数シグネチャは func add(a, b int) int
であり、直接レシーバーはありません。これは go のパッケージ内で定義されており、直接呼び出すことができます。たとえば、例の main
関数は add
関数を呼び出します。
例の関数名は小文字の add
で始まるため、そのスコープは宣言されたパッケージにのみ属し、他のパッケージでは使用できません。大文字の場合、関数のスコープは広く、他のパッケージから呼び出すことができます。これは、Go 言語における大文字と小文字の使用でもあります。たとえば、Java では、スコープを宣言する特別なキーワード private
、protect
、public# があります。 ##など
/* 提供的常用库,有一些常用的方法,方便使用 */ package lib // 一个加法实现 // 返回a+b的值 func Add(a, b int) int { return a + b }
Add メソッドは、他のパッケージから呼び出すことができます。
func# の間に配置されることです。 ## とメソッド名。パラメーターを追加します。このパラメーターはレシーバーなので、定義したメソッドはレシーバーにバインドされ、レシーバーのメソッドと呼ばれます。 <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="go">type person struct {
name string
}
func (p person) String() string{
return "the person name is "+p.name
}</pre><div class="contentsignin">ログイン後にコピー</div></div>
この例では、
とメソッド名の間に追加されたパラメーター (p person)
に注目してください。これがレシーバーです。ここで、型 person
には String
メソッドがあるとします。次に、その使用方法を見てみましょう。 <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="go">func main() {
p:=person{name:"张三"}
fmt.Println(p.String())
}</pre><div class="contentsignin">ログイン後にコピー</div></div>
呼び出しメソッドは非常に簡単です。型変数を使用して呼び出すだけです。型変数とメソッドの前に
演算子があり、この型変数の特定のメソッドが呼び出されることを示しますという意味です。 Go 言語には、値レシーバーとポインター レシーバーの 2 種類のレシーバーがあります。上の例では、値型レシーバーを使用しています。
値型レシーバーによって定義されたメソッドを使用すると、呼び出されたときに実際に値レシーバーのコピーが使用されるため、値に対する操作は元の型変数に影響を与えません。
func main() { p:=person{name:"张三"} p.modify() //值接收者,修改无效 fmt.Println(p.String()) } type person struct { name string } func (p person) String() string{ return "the person name is "+p.name } func (p person) modify(){ p.name = "李四" }
上記の例では、出力される値は依然として
张三 であり、これに対する変更は無効です。ポインタをレシーバとして使用すると、ポインタ レシーバはポインタのコピーを元の値に渡すため、機能します。ポインタのコピーは依然として元の型の値を指しているため、それが変更されると、元の型変数の値にも影響します。 <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="go">func main() {
p:=person{name:"张三"}
p.modify() //指针接收者,修改有效
fmt.Println(p.String())
}
type person struct {
name string
}
func (p person) String() string{
return "the person name is "+p.name
}
func (p *person) modify(){
p.name = "李四"
}</pre><div class="contentsignin">ログイン後にコピー</div></div>
これを変更してポインタの受け取り側になるだけで変更は完了です。
上記の例では、ポインター レシーバー メソッドを呼び出すときに、ポインターではなく値変数も使用していることがわかりましたか。次の を使用しても可能です。
p:=person{name:"张三"} (&p).modify() //指针接收者,修改有效
これも可能です。呼び出しにポインタの使用を強制しない場合、Go コンパイラは、受信側の要件を満たすポインタを取得するのを自動的に支援します。
同様に、値レシーバーのメソッドである場合は、ポインターを使用して呼び出すこともできます。Go コンパイラーは、レシーバーの要件を満たすために自動的に逆参照します (例: で定義されている
String()例の ) メソッドは次のように呼び出すこともできます: <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="go">p:=person{name:"张三"}
fmt.Println((&p).String())</pre><div class="contentsignin">ログイン後にコピー</div></div>
つまり、メソッドを呼び出すときは、値またはポインタのいずれかを使用できますが、これらを厳密に遵守する必要はありません。 Go 言語コンパイラが役立ち、自動的にエスケープされるため、開発者は非常に楽になります。
不管是使用值接收者,还是指针接收者,一定要搞清楚类型的本质:对类型进行操作的时候,是要改变当前值,还是要创建一个新值进行返回?这些就可以决定我们是采用值传递,还是指针传递。
1、含义不同
函数function是一段具有独立功能的代码,可以被反复多次调用,从而实现代码复用。而方法method是一个类的行为功能,只有该类的对象才能调用。
2、方法有接受者,而函数无接受者
Go语言的方法method是一种作用于特定类型变量的函数,这种特定类型变量叫做Receiver(接受者、接收者、接收器);
接受者的概念类似于传统面向对象语言中的this或self关键字;
Go语言的接受者强调了方法具有作用对象,而函数没有作用对象;
一个方法就是一个包含了接受者的函数;
Go语言中, 接受者的类型可以是任何类型,不仅仅是结构体, 也可以是struct类型外的其他任何类型。
3、函数不可以重名,而方法可以重名
只要接受者不同,则方法名可以一样。
4、调用方式不一样
方法是struct对象通过.点号+名称来调用,而函数是直接使用名称来调用。
方法的调用需要指定类型变量调用,函数则不需要
``` var p testMethod.Person p.Name = "tom" p.Age = 123 p.ShowInfo()
注:方法和函数的访问权限都受大小写影响,小写本包,大写全局
5、方法需要指定所属类型,可以是结构体也可以是自定义type,函数则通用
``` func (person Person) ShowInfo(形参) 返回值{ person.Name = "123" person.Age = 12 fmt.Printf("name=%v,age=%v",person.Name,person.Age) } ``` person为类型的形参,类型为Person
6、函数的形参与传参类型需要一致,方法可以改变
``` func (person *Person) ShowInfo(形参) 返回值{ person.Name = "123" person.Age = 12 fmt.Printf("name=%v,age=%v",person.Name,person.Age) }
(1)这里方法的类型形参为指针,调用时可以使用 p.ShowInfo()或者 (&p).ShowInfo(),本质上都是后者,只不过Go的设计者对于方法的调用做了底层优化
func (person Person) ShowInfo(形参) 返回值{ person.Name = "123" person.Age = 12 fmt.Printf("name=%v,age=%v",person.Name,person.Age) }
(2)这里方法的形参类型为数值型,默认为值传递,而在调用时可以使用p.ShowInfo()或者 (&p).ShowInfo(),但依旧是值拷贝
func test01(i *int) { }
(3)对于函数则需保持一致,需要的形参为指针,则传入的形参需为地址值,否则编译无法通过
以上がGo言語のメソッドと関数の違いは何ですかの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。