91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Go語言函數、結構體、方法和接口怎么用

發布時間:2022-05-24 09:19:04 來源:億速云 閱讀:157 作者:iii 欄目:開發技術

本篇內容介紹了“Go語言函數、結構體、方法和接口怎么用”的有關知識,在實際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓小編帶領大家學習一下如何處理這些情況吧!希望大家仔細閱讀,能夠學有所成!

    1. 函數

    Go語言的函數屬于“一等公民”(first-class),也就是說:

    • 函數本身可以作為值進行傳遞。

    • 支持匿名函數和閉包(closure)。

    • 函數可以滿足接口。

    1.1 函數返回值

    同一種類型返回值
    func typedTwoValues() (int, int) {
        return 1, 2
    }
    a, b := typedTwoValues()
    fmt.Println(a, b)
    帶變量名的返回值
    func named Ret Values() (a, b int) {
           a = 1
           b = 2
           return
    }

    函數使用命名返回值時,可以在return中不填寫返回值列表,如果填寫也是可行的

    函數中的參數傳遞

    Go語言中傳入和返回參數在調用和返回時都使用 值傳遞 ,這里需要注意的是 指針、切片和map等引用型對象指向的內容在參數傳遞中不會發生復制,而是將指針進行復制,類似于創建一次引用。

    函數變量

    在Go語言中,函數也是一種類型,可以和其他類型一樣被保存在變量中

    func fire() {
    	fmt.Println("fire")
    }
    func main() {
    	var f func()  //將變量f聲明為func()類型,此時f就被俗稱為“回調函數”。此時f的值為nil。
    	f = fire
    	f()
    }

    1.2 匿名函數——沒有函數名字的函數

    Go語言支持匿名函數,即在需要使用函數時,再定義函數,匿名函數沒有函數名, 只有函數體 ,函數可以被作為一種類型被賦值給函數類型的變量, 匿名函數也往往以變量方式被傳遞 。

    在定義時調用匿名函數

    匿名函數可以在聲明后調用,例如:

    func(data int) {
         fmt.Println("hello", data)
    }(100)
    將匿名函數賦值給變量

    匿名函數體可以被賦值,例如:

    // 將匿名函數體保存到f()中
    f := func(data int) {
           fmt.Println("hello", data)
    }
    // 使用f()調用
    f(100)
    匿名函數用作回調函數

    使用時再定義匿名函數,不使用先在被調用函數里面進行聲明,這就是回調精髓

    // 遍歷切片的每個元素,通過給定函數進行元素訪問?
       func visit(list []int, f func(int)) {
            for _, v := range list {
                  f(v)
            }
       }
       func main() {
    
           // 使用匿名函數打印切片內容
            visit([]int{1, 2, 3, 4}, func(v int) {
                  fmt.Println(v)
            })
       }
    可變參數——參數數量不固定的函數形式

    所有參數都是可變參數:fmt.Println

    func Println(a ...interface{}) (n int, err error) {
        return Fprintln(os.Stdout, a...)
    }

    fmt.Println在使用時,傳入的值類型不受限制,例如:

    fmt.Println(5, "hello", &struct{ a int }{1}, true)

    當可變參數為 interface{} 類型時,可以傳入任何類型的值

    部分參數 是可變參數:fmt.Printf

    fmt.Printf的第一個參數為參數列表,后面的參數是可變參數:

    func Printf(format string, a ...interface{}) (n int, err error) {
    	return Fprintf(os.Stdout, format, a...)
    }
    ------------------------------------------------------
    fmt.Printf("pure string\n")
    fmt.Printf("value: %v %f\n", true, math.Pi)

    1.3 閉包

    閉包可以理解成定義在函數內部的一個函數。本質上,閉包是函數內部和函數外部連接起來的橋梁。簡單來說,閉包=函數+引用環境

    func main() {
    	var f = add()
    	fmt.Printf("f(10): %v\n", f(10))
    	fmt.Printf("f(20): %v\n", f(20))
    	// f(10): 10
    	// f(20): 30
    }
    func add() func(int) int {
    	var x int
    	return func(y int) int {
    		x += y
    		return x
    	}
    }

    1.4 defer語句

    defer語句將其后面跟隨的語句進行延遲處理,被defer的語句按先進后出的方式執行(最先defer的語句最后執行,后被defer的語句先執行)。

    特性:

    • 關鍵字defer用于注冊延遲調用

    • 直到調用return之前才執行(故可用來作資源清理)

    • 多個defer語句,FILO方式執行

    • defer中的變量,在defer聲明時就定義了

    用途:

    • 關閉文件句柄

    • 鎖資源釋放

    • 數據庫連接釋放

    處理運行時發生的錯誤

    Go語言的錯誤處理思想及設計包含以下特征:

    •  一個可能造成錯誤的函數,需要返回值中返回一個 錯誤接口(error )。如果調用是成功的,錯誤接口將返回nil,否則返回錯誤。

    • 在函數調用后需要檢查錯誤,如果發生錯誤,進行必要的錯誤處理。

    錯誤接口的定義格式

    error是Go系統聲明的接口類型,代碼如下:

    type error interface {
        Error() string    // 返回錯誤的具體描述.
    }

    所有符合Error() string格式的接口都能實現錯誤接口。

    定義一個錯誤

    在Go語言中,使用errors包進行錯誤的定義,格式如下:

    var err = errors.New("this is an error")

    錯誤字符串由于相對固定,一般在包作用域聲明, 應盡量減少在使用時直接使用errors.New返回。

    宕機(panic)——程序終止運行

    手動觸發宕機

    Go語言可以在程序中手動觸發宕機,讓程序崩潰,這樣開發者可以及時地發現錯誤,同時減少可能的損失。

    Go語言程序在宕機時,會將堆棧和goroutine信息輸出到控制臺,所以宕機也可以方便地知曉發生錯誤的位置。

    package main
    func main() {
    panic("crash")
    }

    panic()的參數可以是任意類型,

    當panic()觸發的宕機發生時,panic()后面的代碼將不會被運行,但是在panic()函數前面已經運行過的defer語句依然會在宕機發生時發生作用,

    1.5 宕機恢復(recover)——防止程序崩潰

    無論是代碼運行錯誤由Runtime層拋出的panic崩潰,還是主動觸發的panic崩潰,都可以配合defer和recover實現錯誤捕捉和恢復,讓代碼在發生崩潰后允許繼續運行。

    Go沒有異常系統,其使用panic觸發宕機類似于其他語言的拋出異常,那么recover的宕機恢復機制就對應try/catch機制。

    panic和recover的關系:

    • 有panic沒recover,程序宕機。

    • 有panic也有recover捕獲,程序不會宕機。執行完對應的defer后,從宕機點退出當前函數后繼續執行。

    提示:雖然panic/recover能模擬其他語言的異常機制,但并不建議代表編寫普通函數也經常性使用這種特性。

    2. 結構體

    結構體成員是由一系列的成員變量構成,這些成員變量也被稱為“字段”。

    字段有以下特性:

    • 字段擁有自己的類型和值。

    • 字段名必須唯一。

    • 字段的類型也可以是結構體,甚至是字段所在結構體的類型。

    Go語言中沒有“類”的概念,也不支持“類”的繼承等面向對象的概念。

    Go語言的結構體與“類”都是復合結構體,但Go語言中結構體的內嵌配合接口比面向對象具有更高的擴展性和靈活性。

    Go語言不僅認為結構體能擁有方法,且每種自定義類型也可以擁有自己的方法。

    2.1 定義與給結構體賦值

    基本形式:

    type Point struct {
    	X int
    	Y int
    }
    var p Point
    p.X = 10
    p.Y = 20

    結構體的定義只是一種內存布局的描述,只有當結構體實例化時,才會真正地分配內存

    創建指針類型的結構體:

    type Player struct {
    	name string
    	age int
    }
    p = new(Player)
    p.name = "james"
    p.age = 40

    取結構體的地址實例化:

    //使用結構體定義一個命令行指令(Command),指令中包含名稱、變量關聯和注釋等
    type Command struct {
    	name string
    	Var *int
    	comment string
    }
    var version int = 1
    cmd := &Command{}
    cmd.name = "version"
    cmd.Var = &version
    cmd.comment = "show version"

    使用鍵值對填充結構體:

    type People struct {
    	name string
    	child *People
    }
    relation := &People{
    	name: "爺爺"
    	child: &People{
    		name: "爸爸"
    		child: &People{
    			name: "我"
    		},
    	}
    }

    3. 方法

    Go語言中的方法(Method)是一種作用于特定類型變量的函數。這種特定類型變量叫做接收器( Receiver )。

    如果將特定類型理解為結構體或“類”時,接收器的概念就類似于其他語言中的 this 或者 self 。

    3.1 結構體方法

    創建一個背包 Bag 結構體為其定義把物品放入背包的方法 insert :

    type Bag struct {
    	items[] int
    }
    func (b *Bag) insert(itemid int) {
    	b.items = append(b.items, itemid)
    } 
    func main() {
    	b := new(Bag)
    	b.insert(1001)
    }

    (b*Bag) 表示接收器,即 Insert 作用的對象實例。每個方法只能有一個接收器。

    3.2 接收器

    接收器是方法作用的目標

    接收器根據接收器的類型可分:

    • 指針接收器

    • 非指針接收器

    • 兩種接收器在使用時會產生不同的效果。根據效果的不同,兩種接收器會被用于不同性能和功能要求的代碼中。

    指針接收器

    由于指針的特性,調用方法時,修改接收器指針的任意成員變量,在方法結束后,修改都是有效的。

    // 定義屬性結構
    type Property struct {
    	value int
    }
    // 設置屬性值方法
    func (p *Property) setVal(val int) {
    	p.value = val
    }
    // 獲取屬性值方法
    func (p *Property) getVal() int {
    	return p.value
    }
    func main() {
    	p := new(Property)
    	p.value = 123
    	fmt.Println(p.getVal())
    	p.setVal(666)
    	fmt.Println(p.getVal())
    }
    非指針類型接收器

    當方法作用于非指針接收器時,Go語言會在代碼運行時 將接收器的值復制一份 。在非指針接收器的方法中可以獲取接收器的成員值, 但修改后無效 。

    type Point struct {
    	x, y int
    }
    func (p Point) add(other Point) Point {
    	return Point{p.x + other.x, p.y + other.y}
    }
    func main() {
    	// 初始化點
    	p1 := Point{1, 1}
    	p2 := Point{2, 2}
    	res := p1.add(p2)
    	fmt.Println(res)
    
    	p3 := Point{3, 3}
    	p4 := p1.add(p2).add(p3)
    	fmt.Println(p4)
    }

    指針接收器和非指針接收器的使用:

    指針和非指針接收器的使用在計算機中, 小對象 由于值復制時的速度較快,所以適合使用非指針接收器。 大對象 因為復制性能較低,適合使用指針接收器,在接收器和參數間傳遞時不進行復制,只是傳遞指針。

    4. 接口

    接口是雙方約定的一種合作協議。接口實現者不需要關心接口會被怎樣使用,調用者也不需要關心接口的實現細節。 接口是一種類型,也是一種抽象結構,不會暴露所含數據的格式、類型及結構。

    4.1 聲明接口

    type 接口類型名 interface {
    	方法1(參數列表) 返回值
    	...
    }

    Go語言的接口在命名時,一般會在單詞后面添加er,如有寫操作的接口叫Writer,有字符串功能的接口叫Stringer,有關閉功能的接口叫Closer等

    方法名:當方法名首字母是大寫時,且這個接口類型名首字母也是大寫時,這個方法可以被接口所在的包(package)之外的代碼訪問。

    io包中提供的Writer接口:

    type Writer interface {
    	Write(p []type) (n int, err error)
    }

    4.2 實現接口

    實現接口的條件:

    • 接口的方法與實現接口的類型方法格式一致

    • 接口中所有方法均被實現

    例:為了抽象數據寫入的過程,定義Data Writer接口來描述數據寫入需要實現的方法。

    // 定義一個數據寫入器接口
    type DataWriter interface {
    	WriteData(data interface{}) error
    }
    // 定義文件結構,用于實現DataWriter
    type file struct {
    }
    // 實現DataWriter接口的方法
    func (d *file) WriteData(data interface{}) error {
    	// 模擬寫入數據
    	fmt.Println("Write Data:", data)
    	return nil
    }
    func main() {
    	// 實例化file
    	f := new(file)
    	// 聲明一個DataWriter接口
    	var writer DataWriter
    	// 將接口賦值,也就是*file
    	writer = f
    	writer.WriteData("one line data")
    }

    Go語言的接口實現是隱式的,無須讓實現接口的類型寫出實現了哪些接口。這個設計被稱為非侵入式設計。

    “Go語言函數、結構體、方法和接口怎么用”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識可以關注億速云網站,小編將為大家輸出更多高質量的實用文章!

    向AI問一下細節

    免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

    AI

    建阳市| 中江县| 江陵县| 聂拉木县| 津市市| 郸城县| 云霄县| 湘西| 中江县| 新郑市| 大连市| 察隅县| 牡丹江市| 尉犁县| 上栗县| 天柱县| 泰顺县| 民权县| 黄骅市| 方正县| 湖北省| 萍乡市| 正阳县| 五莲县| 衡东县| 高安市| 桦川县| 贺兰县| 克拉玛依市| 乌鲁木齐市| 昌江| 乐昌市| 南平市| 鹿泉市| 陕西省| 东乡县| 咸阳市| 钟祥市| 特克斯县| 渝中区| 呼玛县|