中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

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

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

go語言基本語法有哪些

發布時間:2022-01-18 10:24:54 來源:億速云 閱讀:164 作者:iii 欄目:互聯網科技

本篇內容主要講解“go語言基本語法有哪些”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學習“go語言基本語法有哪些”吧!

一、描述

go語言是直接將源碼編譯成二進制機器碼的語言;它支持面向對象、也支持函數式編程;go是強類型語言;Go 編程語言原生支持并發。Go 使用 Go 協程(Goroutine) 和信道(Channel)來處理并發。

二、基本語法

1、切片與數組差別:切片是動態化數組,切片是注意兩者初始化和函數的區別

a.初始化差別

數組需要指定大小,不指定也會根據初始化的自動推算出大小,不可改變 

a:=[...] int {1,2,3} ; a:=[3] int {1,2,3}

切片不需要指定大小

a:=[] int {1,2,3}; a:=make([]int,3); a:=make([] int ,3,5)

b.函數傳遞:

數組需要明確指定大小,數組是值傳遞,不同的數組總是代表不同的存儲。

切片不需要明確指定大小,切片是地址傳遞。多個切片如果表示同一個數組的片段,它們可以共享數據;因此一個切片和相關數組的其他切片是共享存儲的。

func changeArray(a [3]int) {//數組
    a[0] = 100
}
func changeSlice(s []int) {//切片
    s[0] = 100
}

func main(){

    a := [...]int{1, 2, 3}
    changeArray(a)
    fmt.Println(a[0]) //值傳遞,輸出結果:1

    var s []int = []int{1, 2, 3, 4}
    fmt.Println(len(s), cap((s)))
    s = append(s, 6, 7, 8)
    fmt.Println(len(s), cap(s))
    changeSlice(s)
    fmt.Println(s[0]) //地址傳遞,輸出結果:100

}

c.切片和垃圾回收

切片的底層指向一個數組,該數組的實際容量可能要大于切片所定義的容量。只有在沒有任何切片指向的時候,底層的數組內層才會被釋放,這種特性有時會導致程序占用多余的內存。

示例 函數 FindDigits 將一個文件加載到內存,然后搜索其中所有的數字并返回一個切片。

var digitRegexp = regexp.MustCompile("[0-9]+")

func FindDigits(filename string) []byte {
    b, _ := ioutil.ReadFile(filename)
    return digitRegexp.Find(b)
}

這段代碼可以順利運行,但返回的 []byte 指向的底層是整個文件的數據。只要該返回的切片不被釋放,垃圾回收器就不能釋放整個文件所占用的內存。換句話說,一點點有用的數據卻占用了整個文件的內存。

想要避免這個問題,可以通過拷貝我們需要的部分到一個新的切片中:

func FindDigits(filename string) []byte {
   b, _ := ioutil.ReadFile(filename)
   b = digitRegexp.Find(b)
   c := make([]byte, len(b))
   copy(c, b)
   return c
}

2.數組和Map,數組的輸出按照數組的放置順序,但是Map是無序輸出的,每次遍歷的順序不一樣;

var m = map[string]int{
        "unix":         0,
        "python":       1,
        "go":           2,
        "javascript":   3,
        "testing":      4,
        "philosophy":   5,
        "startups":     6,
        "productivity": 7,
        "hn":           8,
        "reddit":       9,
        "C++":          10,
    }
    var keys []string
    for k := range m {
        keys = append(keys, k)
    }
    sort.Strings(keys)
    for _, k := range keys {
        fmt.Println("Key:", k, "Value:", m[k])
    }

3.go語言中的指針

指針是一種存儲變量內存地址(Memory Address)的變量。

go語言基本語法有哪些

如上圖所示,變量 b 的值為 156,而 b 的內存地址為 0x1040a124。變量 a 存儲了 b 的地址。我們就稱 a 指向了 b

指針變量的類型為 *T,該指針指向一個 T 類型的變量。

&b  獲取b的內存地址值;*a 則是獲取a值對應物理地址值的b值:156;

向函數傳遞指針參數

func change(val *int) {  
    *val = 55
}
func main() {  
    a := 58
    fmt.Println("value of a before function call is",a)
    b := &a
    change(b)
    fmt.Println("value of a after function call is", a)
}

4.那么什么時候使用指針接收器,什么時候使用值接收器?

/*
使用值接收器的方法。
*/
func (e Employee) changeName(newName string) {
    e.name = newName
}

/*
使用指針接收器的方法。
*/
func (e *Employee) changeAge(newAge int) {
    e.age = newAge
}

一般來說,指針接收器可以使用在:對方法內部的接收器所做的改變應該對調用者可見時。

指針接收器也可以被使用在如下場景:當拷貝一個結構體的代價過于昂貴時。考慮下一個結構體有很多的字段。在方法內使用這個結構體做為值接收器需要拷貝整個結構體,這是很昂貴的。在這種情況下使用指針接收器,結構體不會被拷貝,只會傳遞一個指針到方法內部使用。

在其他的所有情況,值接收器都可以被使用。

5.在方法中使用值接收器 與 在函數中使用值參數

這個話題很多Go語言新手都弄不明白。我會盡量講清楚。

當一個函數有一個值參數,它只能接受一個值參數。

當一個方法有一個值接收器,它可以接受值接收器和指針接收器。

讓我們通過一個例子來理解這一點。

package main
import (
    "fmt"
)
type rectangle struct {
    length int
    width  int
}
func area(r rectangle) {
    fmt.Printf("Area Function result: %d\n", (r.length * r.width))
}
func (r rectangle) area() {
    fmt.Printf("Area Method result: %d\n", (r.length * r.width))
}
func main() {
    r := rectangle{
        length: 10,
        width:  5,
    }
    area(r)
    r.area()

    p := &r
    /*
       compilation error, cannot use p (type *rectangle) as type rectangle
       in argument to area
    */
    //area(p)
    p.area()//通過指針調用值接收器
}

6.在方法中使用指針接收器 與 在函數中使用指針參數

和值參數相類似,函數使用指針參數只接受指針,而使用指針接收器的方法可以使用值接收器和指針接收器。

package main
import (
    "fmt"
)
type rectangle struct {
    length int
    width  int
}
func perimeter(r *rectangle) {
    fmt.Println("perimeter function output:", 2*(r.length+r.width))

}
func (r *rectangle) perimeter() {
    fmt.Println("perimeter method output:", 2*(r.length+r.width))
}
func main() {
    r := rectangle{
        length: 10,
        width:  5,
    }
    p := &r //pointer to r
    perimeter(p)
    p.perimeter()
    /*
        cannot use r (type rectangle) as type *rectangle in argument to perimeter
    */
    //perimeter(r)
    r.perimeter()//使用值來調用指針接收器
}

7.并行和并發

并行不一定會加快運行速度,因為并行運行的組件之間可能需要相互通信。在我們瀏覽器的例子里,當文件下載完成后,應當對用戶進行提醒,比如彈出一個窗口。于是,在負責下載的組件和負責渲染用戶界面的組件之間,就產生了通信。在并發系統上,這種通信開銷很小。但在多核的并行系統上,組件間的通信開銷就很高了。所以,并行不一定會加快運行速度!

8.線程與協程區別

線程切換從系統層面遠不止 保存和恢復 CPU上下文這么簡單。操作系統為了程序運行的高效性每個線程都有自己緩存Cache等等數據,操作系統還會幫你做這些數據的恢復操作。所以線程的切換非常耗性能。但是協程的切換只是單純的操作CPU的上下文,所以一秒鐘切換個上百萬次系統都抗的住。但是協程有一個問題,就是系統并不感知,所以操作系統不會幫你做切換。目前的協程框架一般都是設計成 1:N 模式。所謂 1:N 就是一個線程作為一個容器里面放置多個協程。那么誰來適時的切換這些協程?答案是有協程自己主動讓出CPU,也就是每個協程池里面有一個調度器,這個調度器是被動調度的。意思就是他不會主動調度。協程的切換很輕。

9.緩沖信道和非緩沖信道

緩沖的channel:保證往緩沖中存數據先于對應的取數據,簡單說就是在取的時候里面肯定有數據,否則就因取不到而阻塞。

非緩沖的channel:保證取數據先于存數據,就是保證存的時候肯定有其他的goroutine在取,否則就因放不進去而阻塞

到此,相信大家對“go語言基本語法有哪些”有了更深的了解,不妨來實際操作一番吧!這里是億速云網站,更多相關內容可以進入相關頻道進行查詢,關注我們,繼續學習!

向AI問一下細節

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

AI

贵南县| 义乌市| 宿迁市| 定南县| 邛崃市| 永安市| 泰来县| 大连市| 铅山县| 清原| 湘潭市| 新巴尔虎右旗| 台江县| 新余市| 永靖县| 大庆市| 靖江市| 蓬莱市| 惠东县| 水富县| 海原县| 鄂尔多斯市| 六安市| 通许县| 沅陵县| 云梦县| 乡宁县| 兴安盟| 称多县| 江北区| 绩溪县| 兰州市| 彰化市| 威信县| 镶黄旗| 玉门市| 无棣县| 平山县| 株洲市| 莎车县| 浙江省|