Golang 函數 方法 介面的簡單介紹

函數

函數是基本的程式碼塊,通常我們會將一個功能封裝成一個函數,方便我們調用,同時避免程式碼臃腫複雜。

函數的基本格式

func TestFunc(a int, b string) (int, string) {
    // body
}

函數基本在每種語言都經常使用,所以感覺沒什麼記錄的。

方法

方法與對象綁定,簡單的來講只是將對象傳遞給函數使其成為一種特殊(只屬於該對象)的函數,因為Golang是沒有這個概念(在Golang里,結構體的簡化版),所以也可以將方法理解為類的成員函數,但需要注意的是,在Golang里幾乎所有數據類型都可以與方法綁定。

方法的基本格式

func (a objectType) TestMethod(a int, b string) (int, string) {
    // body
}

先定一個結構體

type Test1 struct {
	aaa int
	bbb int
}

func (t Test1) String() string {
	res := fmt.Sprintf("aaa:%d, bbb:%d", t.aaa, t.bbb)
	return res
}

指針或者值作為綁定對象的區別

指針和值都可以綁定方法,並且我們不需要手動區分,這是因為Golang會自動解引用。

只讀對象的內部變數

指針和值是沒有區別的,下面的程式碼分別使用了值和指針綁定:

func (t *Test1) Sum() int {
	return t.aaa + t.bbb
}

func (t Test1) Mul() int {
	return t.aaa * t.bbb
}

然後我們定義一個對象來分別調用上面的兩個方法:

ttt := Test1{aaa: 5, bbb: 2}
fmt.Println("Sum:", ttt.Sum())
fmt.Println("Mul:", ttt.Mul())

// output:
// Sum: 7
// Mul: 10

修改對象的內部變數

如果需要修改對象的內部變數,就必須在對象的指針類型上定義該方法,下面的程式碼分別使用了值和指針綁定:

func (t *Test1) modifyByAddr(a int) {
	t.aaa = a
}

func (t Test1) modifyByValue(a int) {
	t.aaa = a
}

然後我們定義一個對象來分別調用上面的兩個方法:

fmt.Println("old value:", ttt)
ttt.modifyByValue(222)
fmt.Println("modifyByValue:", ttt)
ttt.modifyByAddr(111)
fmt.Println("modifyByAddr:", ttt)

// output
// old value: aaa:5, bbb:2
// modifyByValue: aaa:5, bbb:2
// modifyByAddr: aaa:111, bbb:2

函數與方法的區別

通過上面的例子來說明

  • 函數將變數當做參數傳入Test1Sum(ttt)
  • 方法是被變數調用ttt.Mul()ttt.Sum()

介面

介面定義了一組方法,但這些方法並沒有實現,使用該介面的前提是對象實現了介面內部的方法,這裡需要特別注意,對象必須實現介面里的所以方法,或者會報錯。
下面我們定義了一個介面,包含兩個方法,其中modify(int, int)我們沒有在結構體Test1里實現。

type TestInterface interface {
	Sum() int
	modify(int, int)
}

我們將對象賦給介面的時候就會報錯,程式碼如下:

ttt := new(Test1)
ttt.aaa = 5
ttt.bbb = 2

var test1Face TestInterface
test1Face = ttt

這時候就會報錯如下資訊:

src/test.go:44:14: cannot use ttt (variable of type Test1) as type TestInterface in assignment:
	Test1 does not implement TestInterface (Sum method has pointer receiver)

完整程式碼

package main

import "fmt"

type TestInterface interface {
	Sum() int
	modify(int, int)
}

type Test1 struct {
	aaa int
	bbb int
}

func (t *Test1) modify(a, b int) {
	t.aaa = a
	t.bbb = b
}

func (t *Test1) Sum() int {
	return t.aaa + t.bbb
}

func (t Test1) Mul() int {
	return t.aaa * t.bbb
}

func Test1Sum(t *Test1) int {
	return t.aaa + t.bbb
}

func (t *Test1) modifyByAddr(a int) {
	t.aaa = a
}

func (t Test1) modifyByValue(a int) {
	t.aaa = a
}

func (t Test1) String() string {
	res := fmt.Sprintf("aaa:%d, bbb:%d", t.aaa, t.bbb)
	return res
}

func main() {
	ttt := new(Test1)
	ttt.aaa = 5
	ttt.bbb = 2

	var test1Face TestInterface
	test1Face = ttt
	test1Face.modify(123, 456)

	fmt.Println("Sum:", ttt.Sum())
	fmt.Println("Mul:", ttt.Mul())
	fmt.Println("Test1Sum:", Test1Sum(ttt))

	fmt.Println("old value:", ttt)
	ttt.modifyByValue(222)
	fmt.Println("modifyByValue:", ttt)
	ttt.modifyByAddr(111)
	fmt.Println("modifyByAddr:", ttt)
}

Tags: