最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Go語言七篇入門教程三函數(shù)方法及接口

 更新時間:2021年11月09日 16:43:08   作者:小生凡一  
這篇文章主要為大家介紹了Go語言的函數(shù)方法及接口的示例詳解,本文是Go語言七篇入門系列文章,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步

參考書籍:
《go語言程序設(shè)計》

1. 函數(shù)

每個函數(shù)聲明都包含一個名字,一個形參列表,一個可選的返回列表以及函數(shù)體:

func name(parameter-list)(result-list){
	body
}

形參列表:指定另一組變量的參數(shù)名和參數(shù)類型,這些局部變量都由調(diào)用者提供的提供的實參傳遞而來的。

返回列表:指定了函數(shù)返回值的類型。當(dāng)函數(shù)返回一個未命名的返回值或者沒有返回值的時候,返回列表的圓括號可以忽略。

func FanOne(x float64) float64 {
	return math.Sqrt(x*x)
}
fmt.Println(FanOne(3)) // 3

這里的x就是形參,3就是傳入函數(shù)的實參

// 定義一個求兩數(shù)之和的函數(shù)
func add(a,b int) int  {
    return a + b
}

func main() {
    sum := add(1,2)
    fmt.Println(sum)
}

2. 方法

在 Go 語言中,結(jié)構(gòu)體就像是類的一種簡化形式,那么面向?qū)ο蟪绦騿T可能會問:類的方法在哪里呢?在 Go 中有一個概念,它和方法有著同樣的名字,并且大體上意思相同:Go 方法是作用在接收者(receiver)上的一個函數(shù),接收者是某種類型的變量。因此方法是一種特殊類型的函數(shù)。

接收者類型可以是(幾乎)任何類型,不僅僅是結(jié)構(gòu)體類型:任何類型都可以有方法,甚至可以是函數(shù)類型,可以是 int、bool、string 或數(shù)組的別名類型。但是接收者不能是一個接口類型,因為接口是一個抽象定義,但是方法卻是具體實現(xiàn);如果這樣做會引發(fā)一個編譯錯誤:invalid receiver type…。

最后接收者不能是一個指針類型,但是它可以是任何其他允許類型的指針。

一個類型加上它的方法等價于面向?qū)ο笾械囊粋€類。一個重要的區(qū)別是:
在 Go 中,類型的代碼和綁定在它上面的方法的代碼可以不放置在一起,它們可以存在在不同的源文件,唯一的要求是:它們必須是同一個包的。

類型 T(或 *T)上的所有方法的集合叫做類型 T(或 *T)的方法集(method set)。

因為方法是函數(shù),所以同樣的,不允許方法重載,即對于一個類型只能有一個給定名稱的方法。但是如果基于接收者類型,是有重載的:具有同樣名字的方法可以在 2 個或多個不同的接收者類型上存在,比如在同一個包里這么做是允許的:

func (a *denseMatrix) Add(b Matrix) Matrix
func (a *sparseMatrix) Add(b Matrix) Matrix

別名類型沒有原始類型上已經(jīng)定義過的方法。

定義方法的一般格式如下:

func (recv receiver_type) methodName(parameter_list) (return_value_list) { 
	...
 }

在方法名之前,func 關(guān)鍵字之后的括號中指定 receiver。

如果 recvreceiver的實例,Method1是它的方法名,那么方法調(diào)用遵循傳統(tǒng)的object.name 選擇器符號:recv.Method1()

如果recv 是一個指針,Go 會自動解引用。

如果方法不需要使用 recv 的值,可以用 _ 替換它,比如:

func (_ receiver_type) methodName (parameter_list) (return_value_list) {
			 ...
 }

recv 就像是面向?qū)ο笳Z言中的 this 或 self,但是 Go 中并沒有這兩個關(guān)鍵字。隨個人喜好,你可以使用 this 或 self 作為 receiver 的名字。下面是一個結(jié)構(gòu)體上的簡單方法的例子:

package main
import "fmt"
type TwoInts struct {
	a int
	b int
}
func main() {
	two1 := new(TwoInts)
	two1.a = 12
	two1.b = 10
	fmt.Printf("The sum is: %d\n", two1.AddThem())
	fmt.Printf("Add them to the param: %d\n", two1.AddToParam(20))
	two2 := TwoInts{3, 4}
	fmt.Printf("The sum is: %d\n", two2.AddThem())
}
func (tn *TwoInts) AddThem() int {
	return tn.a + tn.b
}
func (tn *TwoInts) AddToParam(param int) int {
	return tn.a + tn.b + param
}

輸出:

The sum is: 22
Add them to the param: 42
The sum is: 7

方法是可以重載的,這里的話就有那么一點面向?qū)ο髢?nèi)味了~

比如

func (a *aaa) Fan(){
}
func (a *bbb)Fan(){
}

這種是可以的~

3. 接口

Go 語言不是一種 “傳統(tǒng)” 的面向?qū)ο缶幊陶Z言:它里面沒有類和繼承的概念。

接口是golang中實現(xiàn)多態(tài)性的好途徑。接口類型是對其他類型行為的概括與抽象,對于一個具體的類型,無需聲明它實現(xiàn)了哪些接口,只提供接口所必須的方法即可。

之前介紹的類型都是具體類型。go語言中還有一種類型稱為接口類型。接口是一種抽象類型,他并沒有暴露所含數(shù)據(jù)的布局或者內(nèi)部結(jié)構(gòu),當(dāng)然也沒有那些數(shù)據(jù)的基本操作,它所提供的僅僅是一些方法而已,如果你拿到了一個接口,你無從知道他是什么,但是你能知道的僅僅是它能做什么,或者更精確地講,僅僅是它提供了哪些方法。

接口定義了一組方法(方法集),但是這些方法不包含(實現(xiàn))代碼:它們沒有被實現(xiàn)(它們是抽象的)。接口里也不能包含變量。

通過如下格式定義接口:

type Namer interface {
    Method1(param_list) return_type
    Method2(param_list) return_type
    ...
}

上面的 Namer 是一個 接口類型。

(按照約定,只包含一個方法的)接口的名字由方法名加 er 后綴組成,例如 Printer、Reader、WriterLogger、Converter 等等。還有一些不常用的方式(當(dāng)后綴 er 不合適時),比如 Recoverable,此時接口名以 able 結(jié)尾,或者以 I 開頭(像 .NETJava 中那樣)。

Go 語言中的接口都很簡短,通常它們會包含 0 個、最多 3 個方法。

不像大多數(shù)面向?qū)ο缶幊陶Z言,在 Go 語言中接口可以有值,一個接口類型的變量或一個 接口值 :var ai Namerai 是一個多字(multiword)數(shù)據(jù)結(jié)構(gòu),它的值是 nil。它本質(zhì)上是一個指針,雖然不完全是一回事。指向接口值的指針是非法的,它們不僅一點用也沒有,還會導(dǎo)致代碼錯誤。

類型(比如結(jié)構(gòu)體)可以實現(xiàn)某個接口的方法集;這個實現(xiàn)可以描述為,該類型的變量上的每一個具體方法所組成的集合,包含了該接口的方法集。實現(xiàn)了 Namer 接口的類型的變量可以賦值給 ai(即 receiver 的值),方法表指針(method table ptr)就指向了當(dāng)前的方法實現(xiàn)。當(dāng)另一個實現(xiàn)了 Namer 接口的類型的變量被賦給 aireceiver 的值和方法表指針也會相應(yīng)改變。

類型不需要顯式聲明它實現(xiàn)了某個接口:接口被隱式地實現(xiàn)。多個類型可以實現(xiàn)同一個接口。

實現(xiàn)某個接口的類型(除了實現(xiàn)接口方法外)可以有其他的方法。一個類型可以實現(xiàn)多個接口。

接口類型可以包含一個實例的引用, 該實例的類型實現(xiàn)了此接口(接口是動態(tài)類型)。

即使接口在類型之后才定義,二者處于不同的包中,被單獨編譯:只要類型實現(xiàn)了接口中的方法,它就實現(xiàn)了此接口。
所有這些特性使得接口具有很大的靈活性。

第一個例子:

package main
import "fmt"
type Shaper interface {
	Area() float32
}
type Square struct {
	side float32
}
func (sq *Square) Area() float32 {
	return sq.side * sq.side
}
func main() {
	sq1 := new(Square)
	sq1.side = 5
	var areaIntf Shaper
	areaIntf = sq1
	// shorter,without separate declaration:
	// areaIntf := Shaper(sq1)
	// or even:
	// areaIntf := sq1
	fmt.Printf("The square has area: %f\n", areaIntf.Area())
}

輸出:

The square has area: 25.000000

上面的程序定義了一個結(jié)構(gòu)體 Square 和一個接口 Shaper,接口有一個方法 Area()。
main() 方法中創(chuàng)建了一個 Square 的實例。在主程序外邊定義了一個接收者類型是 Square 方法的 Area(),用來計算正方形的面積:結(jié)構(gòu)體 Square 實現(xiàn)了接口 Shaper 。

所以可以將一個 Square 類型的變量賦值給一個接口類型的變量:areaIntf = sq1 。
現(xiàn)在接口變量包含一個指向 Square 變量的引用,通過它可以調(diào)用 Square 上的方法 Area()。當(dāng)然也可以直接在 Square 的實例上調(diào)用此方法,但是在接口實例上調(diào)用此方法更令人興奮,它使此方法更具有一般性。接口變量里包含了接收者實例的值和指向?qū)?yīng)方法表的指針。

這是 多態(tài) 的 Go 版本,多態(tài)是面向?qū)ο缶幊讨幸粋€廣為人知的概念:根據(jù)當(dāng)前的類型選擇正確的方法,或者說:同一種類型在不同的實例上似乎表現(xiàn)出不同的行為。

如果 Square 沒有實現(xiàn) Area() 方法,編譯器將會給出清晰的錯誤信息:

cannot use sq1 (type *Square) as type Shaper in assignment:
*Square does not implement Shaper (missing Area method)

如果 Shaper 有另外一個方法 Perimeter(),但是Square 沒有實現(xiàn)它,即使沒有人在 Square 實例上調(diào)用這個方法,編譯器也會給出上面同樣的錯誤。

擴展一下上面的例子,類型 Rectangle 也實現(xiàn)了 Shaper 接口。接著創(chuàng)建一個 Shaper 類型的數(shù)組,迭代它的每一個元素并在上面調(diào)用 Area() 方法,以此來展示多態(tài)行為:

package main
import "fmt"
type Shaper interface {
	Area() float32
}
type Square struct {
	side float32
}
func (sq *Square) Area() float32 {
	return sq.side * sq.side
}
type Rectangle struct {
	length, width float32
}
func (r Rectangle) Area() float32 {
	return r.length * r.width
}
func main() {
	r := Rectangle{5, 3} // Area() of Rectangle needs a value
	q := &Square{5}      // Area() of Square needs a pointer
	// shapes := []Shaper{Shaper(r), Shaper(q)}
	// or shorter
	shapes := []Shaper{r, q}
	fmt.Println("Looping through shapes for area ...")
	for n, _ := range shapes {
		fmt.Println("Shape details: ", shapes[n])
		fmt.Println("Area of this shape is: ", shapes[n].Area())
	}
}

輸出:

Looping through shapes for area ...
Shape details:  {5 3}
Area of this shape is:  15
Shape details:  &{5}
Area of this shape is:  25

在調(diào)用 shapes[n].Area() 這個時,只知道 shapes[n] 是一個 Shaper 對象,最后它搖身一變成為了一個 SquareRectangle 對象,并且表現(xiàn)出了相對應(yīng)的行為。

也許從現(xiàn)在開始你將看到通過接口如何產(chǎn)生 更干凈、更簡單 及 更具有擴展性 的代碼。在 11.12.3 中將看到在開發(fā)中為類型添加新的接口是多么的容易。

下面是一個更具體的例子:有兩個類型 stockPositioncar,它們都有一個 getValue() 方法,我們可以定義一個具有此方法的接口 valuable。接著定義一個使用 valuable 類型作為參數(shù)的函數(shù) showValue(),所有實現(xiàn)了 valuable 接口的類型都可以用這個函數(shù)。

package main
import "fmt"
type stockPosition struct {
	ticker     string
	sharePrice float32
	count      float32
}
/* method to determine the value of a stock position */
func (s stockPosition) getValue() float32 {
	return s.sharePrice * s.count
}
type car struct {
	make  string
	model string
	price float32
}
//使用方法去獲取車的值
func (c car) getValue() float32 {
	return c.price
}
/* contract that defines different things that have value */
type valuable interface {
	getValue() float32
}
func showValue(asset valuable) {
	fmt.Printf("Value of the asset is %f\n", asset.getValue())
}
func main() {
	var o valuable = stockPosition{"GOOG", 577.20, 4}
	showValue(o)
	o = car{"BMW", "M3", 66500}
	showValue(o)
}

輸出:

Value of the asset is 2308.800049
Value of the asset is 66500.000000

以上就是Go語言七篇入門教程三函數(shù)方法及接口的詳細內(nèi)容,更多關(guān)于Go語言函數(shù)方法及接口的資料請關(guān)注腳本之家其它相關(guān)文章!

如何學(xué)習(xí)Go

如果你是小白,你可以這樣學(xué)習(xí)Go語言~

七篇入門Go語言

第一篇:Go簡介初識

第二篇:程序結(jié)構(gòu)&&數(shù)據(jù)類型的介紹

第四篇:通道與Goroutine的并發(fā)編程

第五篇:文件及包的操作與處理

第六篇:網(wǎng)絡(luò)編程

第七篇:GC垃圾回收三色標(biāo)記

相關(guān)文章

  • Go使用sync.Map來解決map的并發(fā)操作問題

    Go使用sync.Map來解決map的并發(fā)操作問題

    在 Golang 中 map 不是并發(fā)安全的,sync.Map 的引入確實解決了 map 的并發(fā)安全問題,本文就詳細的介紹一下如何使用,感興趣的可以了解一下
    2021-10-10
  • Golang字符串變位詞示例詳解

    Golang字符串變位詞示例詳解

    這篇文章主要給大家介紹了關(guān)于GoLang字符串變位詞的相關(guān)資料,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧。
    2017-10-10
  • Go語言輕量級線程Goroutine用法實例

    Go語言輕量級線程Goroutine用法實例

    這篇文章主要介紹了Go語言輕量級線程Goroutine用法,實例分析了goroutine使用技巧,需要的朋友可以參考下
    2015-02-02
  • golang中的container/heap包使用

    golang中的container/heap包使用

    Golang中的container/heap包提供堆操作,適用于實現(xiàn)了heap.Interface的類型,本文主要介紹了golang中的container/heap包使用,感興趣的可以了解一下
    2025-02-02
  • Golang獲取當(dāng)前時間代碼

    Golang獲取當(dāng)前時間代碼

    本文給大家匯總介紹了golang中的相關(guān)的時間的操作,有需要的小伙伴可以拿走參考下
    2018-10-10
  • Go并發(fā)的方法之goroutine模型與調(diào)度策略

    Go并發(fā)的方法之goroutine模型與調(diào)度策略

    在go中,協(xié)程co-routine被改為goroutine,一個goroutine只占幾kb,因此可以有大量的goroutine存在,另一方面goroutine 的調(diào)度器非常靈活,本文給大家介紹下Go并發(fā)的方法之goroutine模型與調(diào)度策略,感興趣的朋友一起看看吧
    2021-11-11
  • Go語言格式化動詞使用詳解

    Go語言格式化動詞使用詳解

    這篇文章主要介紹了Go語言格式化動詞使用詳解的相關(guān)資料,需要的朋友可以參考下
    2023-08-08
  • Go語言中sync包使用方法教程

    Go語言中sync包使用方法教程

    在Go語言的并發(fā)編程實踐中,性能優(yōu)化總是繞不開的話題,下面這篇文章主要介紹了Go語言中sync包使用方法的相關(guān)資料,文中通過代碼介紹的非常詳細,需要的朋友可以參考下
    2025-03-03
  • Golang中由零值和gob庫特性引起B(yǎng)UG解析

    Golang中由零值和gob庫特性引起B(yǎng)UG解析

    這篇文章主要為大家介紹了Golang中由零值和gob庫特性引起B(yǎng)UG解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-04-04
  • 獲取Golang環(huán)境變量的三種方式小結(jié)

    獲取Golang環(huán)境變量的三種方式小結(jié)

    本文介紹了Golang中獲取環(huán)境變量的三種方式,包含使用Viper包、GoDotEnv包和os包,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2024-11-11

最新評論

青川县| 桃园市| 夏河县| 广宗县| 宾川县| 沙坪坝区| 阳信县| 彩票| 麦盖提县| 乌海市| 北辰区| 武穴市| 汤阴县| 苏尼特左旗| 平泉县| 阳信县| 内乡县| 莎车县| 铜陵市| 靖西县| 沿河| 如东县| 左权县| 襄樊市| 临颍县| 东乡县| 宁都县| 碌曲县| 临桂县| 柳河县| 葵青区| 上饶县| 孝义市| 西和县| 浮山县| 蓝山县| 巴林右旗| 乳源| 定远县| 乌兰浩特市| 邛崃市|