【Go學習】Go(Golang)知識點總結
1,Go介紹
是Google開發的一種靜態強型別、編譯型、併發型,並具有垃圾回收功能的程式語言。
1)環境搭建
①標準包安裝
go1.11.2.darwin-amd64.pkg
檢查安裝成功:在終端輸入:go,出現go命令列表。
②配置環境變數
(1)開啟終端,cd ~
(2)檢視是否有.bash_profile檔案:
ls -all
(3)有則跳過此步,沒有則:
1)建立:touch .bash_profile
2)編輯:open -e .bash_profile
3)自定義GOPATH和GOBIN位置:
export GOPATH=/Users/lwh/program/Go
export GOBIN=$GOPATH/bin
export PATH=$PATH:$GOBIN
(4)編譯:source .bash_profile
終端輸入以下命令。顯示go執行所需的系統環境變數。
go env
③安裝整合開發工具(LiteIDE、Sublime Text、Vim、Emacs、Eclipse、vscode、goland)
Sublime Text3的gosublime這個外掛目前不能用,但是可以在github上下載,相比起來vscode有智慧提示所以採用vscode。
goland使用:
goland應該是最好用的,很少的配置,收費,不缺錢可以支援下正版。
i> 官網下載goland。
ii> 新建一個project,選擇專案location。
如果go環境安裝成功goroot可以選擇。然後create專案。
在專案根目錄建立directory:main。然後在其下方寫一個新的程式:test.go。
package main
import (
"fmt"
)
func main(){
fmt.Println("hello world")
}
Control + shift + R執行即可。#
④工作空間
即建立GOPATH目錄,並在GOPATH下建立三個目錄:
bin:存放編譯後生成的可執行檔案(.exe)
pkg:存放編譯後生成的包檔案(.a)
src:存放專案原始碼(.go)
2,基本語法
1)常量、變數與命名規則
①可見性規則
函式名首字母小寫,表示private;
函式名首字母大寫,表示public。
②常量 const
執行期間不可改變值。
可以涉及計算,但每一個值必須是編譯期就能獲得。
1>內建常量
true、false、iota。
iota
初值為0,作為常量組中常量個數的計數器。
2>定義
const PI float32 = 3.1415926
const PI = 3.1415926 //隱式型別常量定義(省略常量型別,根據賦值自動判斷型別)
const a,b,c = 1, "Go", 'c' //整型常量、字串常量、字元常量 多個常量一起定義
3>列舉
列舉指一系列的常量。
const (
Sunday = iota //0 iota生成了從0開始自動增長的列舉值
Monday //1 後續的iota可以省略
Tuesday //2
)
const (
A = iota //iota每遇到一個const關鍵字,就重置為0
B
)
fmt.Println(Sunday); //0
fmt.Println(Monday); //1
fmt.Println(Tuesday); //2
fmt.Println("-------");
fmt.Println(A); //0
fmt.Println(B); //1
③變數 var
執行期間可改變的值。
變數名是用來引用變數所儲存資料的識別符號,實際上代表變數在記憶體中的地址,可以使用&
獲取。
1>定義
var count int = 10 //格式為:var <variableName> [variableType]
var count = 10 //預設
count: = 10 //用:代替var的預設
2>變數的型別零值
即初始化值。
型別 | 零值 |
---|---|
bool | false |
int、float、byte\rune | 0 |
complex | 0+0i |
string | “” |
pointer、function、interface、slice、channel、map | nil |
④識別符號命名規則
i> 以字母或下劃線開始
ii> 由字母、數字、下劃線組成
iii> 避免關鍵字
iv> 大小寫區分為不同的變數
2)資料型別
①基本資料型別
1> 布林型 bool (1 Byte)
取值範圍:true | false。
2> 整型
進位制(4種):
123 //十進位制
0123 //八進位制 以0開頭
0x123 //十六進位制 以0x開頭
1e3 //指數形式 由數字和e組成 1*(10^3) = 1000
有無符號整型:
int //有符號整型
uint //無符號整型
精度控制整數:
型別 | 位元組長度 | 取值範圍 |
---|---|---|
int | 4/8 | 由作業系統決定。32位機:int32,64位機int64 |
int8 | 1 | -128~127 (- 2^ 7 ~ (2^ 7 -1) ) |
int 16 | 2 | - 2^ 15 ~ (2^ 15 -1) |
int 32 | 4 | - 2^ 31 ~ (2^ 31 -1) |
int 64 | 8 | - 2^ 63 ~ (2^ 63 -1) |
- | - | - |
uint | 4/8 | |
uint8 | 1 | -128~127 (- 2^ 8 ~ (2^ 7) ) |
uint 16 | 2 | …… |
uint 32 | 4 | …… |
uint 64 | 8 | …… |
位元組型 byte(1byte) == uint8
本質是uint8的型別,使用效果完全一樣。
使用該別名是為了增強程式碼的可讀性,告知現在是進行位元組處理。
主要作用:表示和儲存ASCII碼,即處理字元。
字元型
字元以ASCII的形式儲存到記憶體中。所以一個byte型資料直接輸出就是uint8整數形式;也可以將對應的ASCII碼轉換成相應的字元。
rune型別 == int32
Go語言處理Unicode時專門的資料型別,完全等價於int32。
使用該別名是為了增強程式碼的可讀性,告知現在是進行Unicode字元處理。
3> 浮點型(實數)
表示形式:
1.25
1.23e3
型別 | 位元組長度 | 精確位數 |
---|---|---|
float32 32位浮點型 | 4 | 精確到小數點後7位 |
float64 64位浮點型 | 8 | 精確到小數點後15位 |
浮點數存在舍入誤差,所以避免極大數和極小數相加減丟失極小數。
4> 複數型
var cp complex64 = 1.2 + 3.4i //複數:a+bi形式的數(i = 根號-1)。
real(cp) //即1.2,fmt內建包計算實部的函式
imag(cp) //即3.4,fmt內建包計算虛部的函式
型別 | 位元組長度 |
---|---|
complex64 | 8 |
complex128 | 16 |
5> uintptr 指標型別
uintptr是可以儲存指標的無符號整數型別,可以儲存32位或64位的指標。根據作業系統決定指標位數。
//一般表現形式:var <指標變數名> * <基型別>
var i_pointer * int //指向整型的變數的指標i_pointer
var i int = 100; i_pointer = &i //將i的記憶體地址存放到i_pointer中
fmt.Println( * i_pointer ) //通過指標i_pointer讀取對應地址存放的資料,結果輸出為100。
使用注意:
- 指標型別初始化預設值為nil,Go中沒有NULL常量。
- Go中不支援指標運算。
- Go不支援
→
運算子,直接用.
選擇符操作指標物件成員。
②值型別和引用型別
1>值型別
包括:bool、int、float、byte、複數型(complex)、字串(string)、陣列、結構體、錯誤型別(error)。
值拷貝傳遞。
字串(string)、陣列、結構體又稱為構造型別。
2>引用型別
包括:指標、切片(slice)、字典(map)、通道(channel)、介面(interface)、函式(function)。
③字串(string)
1> 字串內容不可變
2> 字串操作
var str string = "hello"; //字串初始化
fmt.Println(str[2]); //取字元,以0開始。'A' = 65,'a' = 97, 輸出為l = 97+12 = 108
fmt.Println(len(str)); //len()函式 輸出為5
fmt.Println(str + " world");
3>字串遍歷
支援2種方式。
var str string = "hello";
//位元組陣列方式遍歷:(每一個字元型別為byte)
for i := 0; i < len(str); i++ {
fmt.Printf("str[%d] = %v\n", i, str[i]);
}
fmt.Println("-----------");
//Unicode字元方式遍歷:(每一個字元型別為rune)
for i, ch := range str {
fmt.Printf("str[%d] = %v\n", i, ch);
}
4>strings 包
Go標準庫包。
包含了字串查詢函式、字串比較函式、字串位置索引函式、字串追加和替換函式
5>strconv 包
Go標準庫包。
提供了字串與基本資料型別相互轉化的基本函式。
④陣列型別
1>定義
陣列是一組具有相同型別和名稱的變數的集合。
var arr1 [5] int
陣列的元素型別必須是基本資料型別。
2>初始化
var arr1 = [2] int {1,2}
var arr2 = [2] int {1}
var arr3 = [...] int {2,2} //...就是三個英文句號。這個不能省略,否則就成切片了
3>多維陣列
var a[3][4] int //二維陣列定義
var a = [3][4] int {{1,2,3}, {4,5}, {6}}
⑤切片(slice)(變長陣列)
是陣列的一個引用,它會生成一個指向陣列的指標,並通過切片長度關聯到底層陣列部分或者全部元素。
切片還提供了一系列對陣列的管理功能,可以隨時動態的擴充儲存空間,並且可以被隨意傳遞而不會導致所管理的陣列元素被重複賦值。
故切片通常用於實現變長陣列。
1>切片原型
type slice struct {
array unsafe.Pointer //Pointer 是指向一個陣列的指標
len int //len 代表當前切片的長度
cap int //cap 是當前切片的容量。cap 總是大於等於 len 的
}
2>宣告
var slice1 [] int //不要指定陣列長度即切片
3>初始化
預設為nil,長度為0.
var slice1 = [] int {1,2,3,4}
var slice1 = make([] int, 4) //通過內建函式make建立有4個元素的整型切片,元素初始值為int的初始值0.
var slice1 = make([]int, 4, 10) //預留10個元素的儲存空間。
4>運算元組
slice1 = array1 //指定切片引用範圍為陣列全部
slice1 = array1[ : ] //指定切片引用範圍從第一個元素到最後一個元素
slice1 = array1[m:n] //指定切片引用範圍從第m個元素到第n個元素
5>操作
- 訪問:利用下標
- 元素增加:append()
- 元素複製:copy()
⑥字典(Map,Dictionary,雜湊表Hash table)
由鍵值對組成。
1>初始化和建立
未初始化時值為nil。
var map1 map[string] int {} //建立並初始化。鍵用[]包起來。
map1["key1"] = 1
或者用make函式
var map1 map[string] int //建立
map1 = make( map[string] int) //初始化,給map1分配儲存空間
2>訪問和操作
查詢:
var map1 = map[string]int{"key1": 100, "key2": 200}
v, OK := map1["key1"] //查詢一個特定的鍵值對。如果key值存在,則將Key對應的Value值賦予v,OK為true。否則v=0,OK為false。
if OK {
fmt.Println(v, OK) //輸出:100 true
} else {
fmt.Println(v)
}
刪除:
delete(map1,"key1")
⑦通道型別
⑧錯誤型別
⑨型別別名
使用type關鍵字為型別定義別名。
type(
word uint //定義word是uint的別名
小數 float32 //Go支援UTF-8程式設計格式,所以定義時可用非英文字元。
)
var f 小數 = 3.14
var i word = 3
fmt.Println(f)
fmt.Println(i)
⑩型別轉換
格式:<變數A>[:] = <變數A的型別>(<變數B>)
var a int
var f float32 = 3.14
a = int(f) //如果變數A已經定義過了,可以省略`:`
b := int(f)
fmt.Println(a)
fmt.Println(b)
3)運算子與表示式
①分號
用分號來終止語句,但這個分號可以由詞法分析器掃描原始碼過程中自動插入(給每一行末尾根據簡單的規則進行判斷是否需要加分號,所以出現了左大括號約定)。
②註釋
//
或
/* */
③位運算子
運算子 | 描述 | 說明 |
---|---|---|
^ | 取反 | |
& | ||
| |
||
&^ | 標誌位清除運算子 | 從a上清除b上的標誌位 |
<< | 左移 | |
>> |
var a, b byte = 10, 4 //1010
fmt.Println(a) //10b
fmt.Println(^a) //11110101b 2^8-1-10 = 256-11 = 245
fmt.Println(a &^ b) //1010b 清除 10b = 1000b = 8 ;1010b 清除 100b = 不變 = 1010b = 10
fmt.Println(a << 1) //10*2 = 20
④通道運算子(< -)
詳細用法可見通道。
4)輸入輸出
①標準輸出函式:
1>Print
2>Println
3>Printf 格式化輸出
原型:func Printf( format string, a...interface{} ) (n int, err error)
會返回輸出的位元組數和錯誤型別。
作用物件 | 格式字元 | 說明 |
---|---|---|
- | %v | 以基本格式輸出 |
- | %#v | 輸出資料,同時也輸出Go語法表示 |
- | %T | 輸出資料型別 |
- | %% | 輸出% |
bool | %t | 輸出布林值true flase |
int | %b、%d、%o、%x、%X | 以二進位制、十進位制、八進位制、十六進位制(小寫)、十六進位制(大寫) 輸出 |
int | %c | 以Unicode字元格式輸出(否則直接輸出為ASCII碼) |
int | %q | 輸出的每個字元自動加單引號 |
int | %U | Unicode格式:U+1234 == U+%04X |
浮點型、複數 | %b | 無小數部分、兩位指數的科學記數法 |
浮點型、複數 | %e、%E | 科學計數法(小寫e、大寫E) |
浮點型、複數 | %f | 有小數部分,但無指數部分 |
浮點型、複數 | %g、%G | 根據實際情況採用%e(%E)或%f |
字串、切片 | %s | 直接輸出字串或切片 |
字串、切片 | %q | 輸出字串的同時加雙引號 |
字串、切片 | %x、%X | 每個位元組用兩字元的十六進位制數表示 |
指標 | %p | 以0x開頭的十六進位制數表示 |
- | + | 輸出數值正負號對%q(%+q)按ASCII碼輸出 |
- | - | 使用空格填充右側空缺(預設為左側) |
- | # | |
- | ‘ ’ | |
- | 0 | 用前置0代替空格填補空缺 |
fmt.Printf("str[%d] = %v\n", i, str[i]);
②標準輸入函式
1>Scan
原型:
func Scan(a ...interface{} )( n int, err error )
將使用空格分割的連續資料順序存入到引數中(換行也被視為空格)。返回引數的數量n。
var a,b,c int
fmt.Scan(&a,&b,&c)
2>Scanln
原型:
func Scanln(a ...interface{} ) ( n int, err error)
同Scan,不同的是Scanln讀取到換行符才終止錄入。
3>Scanf
原型:
func Scanf( format string, a ...interface{} )( n int, err error}
按照格式化字元讀取資料。
var a,b,c int
fmt.Scanf("%d,%d %d",&a,&b,&c) //嚴格按照格式輸入才可以讀取,如‘1,2 3’
fmt.Print(a)
fmt.Print(b)
fmt.Print(c)
5)順序結構程式
複合語句
用花括號{}
將多條語句組合在一起。
複合語句中的定義的變數是區域性變數,作用域為整個複合語句。
6)選擇結構程式
①if-else
if 表示式1 {
} else if 表示式2 {
} else
注意:if語句塊中不允許執行return語句。
②switch
switch 條件表示式 {
case 常量1:
語句1
……
default:
語句n
}
或者:
switch{
case 條件表達1:
語句1
……
default:
語句n
}
注意:
1>case語句後面不需要break,執行完自動跳出switch語句。
2>如果想執行完當前case後,繼續執行下一個case,在case塊最後面新增語句:fallthrough
var op byte = '+';
switch op {
case '+':
fmt.Println(1);
fallthrough
case '-':
fmt.Println(2)
}
7)迴圈結構程式
只有for迴圈,沒有do和while迴圈。
注意for語句後面沒有括號。
好的程式設計習慣:
- 迴圈變數名儘量短,如:i, j, z, ix等。
- 不要在迴圈中修改迴圈變數
①for基本迴圈結構
var str string = "hello";
for i := 0; i < len(str); i++ {
fmt.Printf("str[%d] = %v\n", i, str[i]);
}
執行順序:表示式1,表示式2,表示式4,表示式3
for 表示式1; 表示式2; 表示式3 {
表示式4
}
②for條件迴圈結構
類似while迴圈。
for 條件表示式{
}
③for無限迴圈結構
用break跳出迴圈。
for{
}
for true{}
for ; ; {}
④for range語句
相當於迭代器,可以對陣列(Array)、切片(Slice)、字典(Map)、通道(Channel)等進行遍歷。在遍歷時會返回一個鍵值對。
var str string = "hello";
for i, ch := range str { //返回的鍵值對i,ch i為下標,ch為值。
fmt.Printf("str[%d] = %v\n", i, ch);
}
可以使用佔位符過濾掉不需要資料。
for _,ch := range str{} //只需要值不需要鍵
for i, _ := range str {} //只需要鍵不需要值
for i := range str {} //只需要鍵不需要值
⑤跳轉語句
1> goto
與LABEL搭配使用。
var a int = 1;
goto LABEL1
a++
LABEL1:
fmt.Println(a);
2> break
3> continue
8)函式
①包宣告部分
包是組成的Go程式的基本單位。每個Go原始碼都要進行包宣告說明當前檔案屬於哪個包。
package <pkgName>
可執行Go程式有且僅有一個main包,有且僅有一個main函式(在main包中)。
原始碼編譯後都會生成*.a檔案。
②第三方包匯入部分
分為如下三種模式。匯入的包沒有使用編譯會報錯(保證程式碼體積小,加快編譯速度)。
1>正常模式
import <pkgName>
舉例:
import "fmt" //匯入包
fmt.Println(v, OK) //輸出:100 true //包內函式呼叫
2>別名模式
包名相近或相同用別名區分。
import 別名 <pkgName>
3>簡便模式
import . <pkgName>
③函式宣告部分
func為關鍵字。允許多返回值。
func funcName(引數列表)(返回值列表){
return result1, result2
}
main函式沒有引數也沒有返回值,如果要傳入引數,可在os.Args變數中儲存。
④變參傳遞
任意數量:
func main() {
a(1,2,3,4,5);
}
func a(args ... int){
fmt.Println(args) //輸出[1 2 3 4 5]
fmt.Println(args[2:]) //輸出[3 4 5] 從索引2開始的數字
}
任意型別的變參,型別指定為空介面interface{}:
func main() {
a(1,2,"s",4,5);
}
func a(args ... interface{}){
fmt.Println(args) //輸出[1 2 s 4 5]
}
⑤閉包(Closure)
內部函式通過某種方式使其可見範圍超出了其定義範圍。
在go語言中,閉包可以作為函式物件或匿名函式。確保只要閉包還被使用,那麼被閉包引用的變數會一直存在。
⑥defer語句
通過defer向函式註冊退出呼叫,當主調函式退出時,defer後的函式才會被執行(不管是否出現異常都會被執行)。
1>最後呼叫
defer fmt.Println("defer ")
fmt.Println("main ")
輸出:
main defer
2>倒序輸出
for i:=0; i<4; i++{
defer fmt.Println(i)
}
輸出:3210
3>匿名函式呼叫
func main() {
fmt.Println("f1 = ",f1())
fmt.Println("f2 = ",f2())
}
//一個延遲執行的函式的變數的值在宣告時,值不延遲
func f1() int{
var i int
defer fmt.Println(i)
i = 1
return 1
}
//被延遲的匿名函式會讀取f2的返回值,或對f2的返回值賦值
func f2()(i int){
defer func(){
i++
}()
return 1
}
4>用於清理工作
defer語句常用來進行函式的清理、釋放資源等工作。
srcFile,err := os.Open("myFile")
defer srcFile.Close
9)結構體
①使用
Go沒有類的概念,通過結構體來實現物件導向程式設計。
type date struct {//定義
year int
}
type student struct {
id int
name string
birthday date
}
func main() {
stu := new(student)
stu.name = "a" //訪問
stu.id = 0
stu.birthday.year = 5
fmt.Println(stu)
}
stu := student{0,"a",date{1}} //物件初始化
②嵌入式結構
③匿名欄位
④方法
1>定義
在普通的函式名前增加繫結型別引數。
type student struct {
id int
name string
fee int
}
type teacher struct {
id int
name string
fee int
}
func main() {
stu := student{0,"a",10}
t1 := teacher{0,"a",10}
fmt.Println(stu.getFee())
fmt.Println(t1.getFee())
}
func (revc student) getFee() int{ //rev為變數,student為struct型別。
return 10+100
}
func (revc teacher) getFee() int{ //類似java中的多型。接收型別不同,方法名可以一樣
return 10+1000
}
如果指標作為一個receiver,那麼是一個引用傳遞。
2>匿名Receiver
3>繼承和重寫
type people struct {
id int
name string
fee int
}
type student struct {
people
school string
}
func main() {
stu := student{people{0,"a",10},"ut"}
fmt.Println(stu.getFee())
}
func (revc student) getFee() int{ //重寫了方法,隱藏了people的getFee方法
return 10+100
}
func (revc people) getFee() int{
return 10+1000
}
4>欄位標籤
10)介面(Interface)
是一組Method的組合,通過Interface來定義物件的一組行為。
①定義
type Speaker interface { //關鍵字:type interface
sayHi()
}
func (s student)sayHi(){
}
func (s student)study(){
}
②介面組合
集合其他介面的功能
type SpeakerLearner interface {
Speaker
study()
}
③空介面
表示任何資料型別。
interface{}
④使用
⑤反射
3,包
1)fmt
是format縮寫。內建基本包。
Package fmt implements formatted I/O with functions analogous to C’s printf and scanf. The format ‘verbs’ are derived from C’s but are simpler.
2)math
①Min、Max
Max(int8) Min(int8) //資料的最大值最小值
3)strings包
4)strconv包
5)bytes包(位元組切片標準庫)
提供了對位元組切片進行讀寫操作的一系列函式和方法。包括:位元組切片處理函式、Buffer物件和Reader物件,類似於strings包。
6)bufio包
實現了對資料I/O介面的緩衝功能。
封裝於介面io.ReadWriter、io.Reader和io.Writer中,在提供緩衝的同時實現了一些文字的基本I/O操作功能。
4,加強
1)記憶體分配機制
①原始碼檔案
UTF-8格式。
②GC
標記-清除演算法。
③記憶體函式
GO有兩種分配記憶體機制,分別是使用內建函式new()和make()。
1>new()
用於給值型別的資料分配記憶體,呼叫成功後返回一個初始化的記憶體塊指標,同時該型別被初始化為“0”.
2>make()
用於給引用型別分配記憶體空間。
make函式建立的是一個引用型別物件,而不是一個記憶體空間的指標。
2)併發程式設計
①基本概念
1>OS提供的併發基礎
程式、
執行緒、
協程(使用者態執行緒):不需要OS進行搶佔式排程,在真正的實現中寄存於執行緒。
2>程式間的併發通訊
- 鎖原語操作
- 訊號量機制
- 共享記憶體(Shared Memory)
多個併發單位在同時訪問共享記憶體時,必須使用互斥鎖等相關機制,保證對共享記憶體的互斥訪問。這早就程式設計複雜。 - 訊息通訊機制(Message Communication Mechanism)
Go語言在處理程式的併發模型時,主要採用訊息機制。
訊息機制規定每個併發單位是自包含的、獨立的個體,並且都有自己的變數,這些變數不能在不同的併發單位之間共享。每個併發單位的輸入輸出只有一種:訊息,即Channel。(類似程式的感覺)
②Goroutine(輕量級執行緒)
是Go語言執行庫的功能(由Go執行時管理(Runtime)),不是OS提供的功能(不是用執行緒實現的,所以支援跨平臺)。
Goroutine就是一段程式碼,一個函式入口,以及在堆上為其分配的一個堆疊。因為節省了頻繁建立和銷燬執行緒的開銷,所以對於程式、執行緒的開銷非常小。可以輕鬆建立上百萬個Goroutine,但它們不是被OS所排程執行的。
Go語言標準庫提供的所有系統呼叫操作(包括同步I/O操作),都會讓出處理機給其他Goroutine。
1>建立(與Channel一起使用)
通過關鍵字go來建立併發執行的Goroutine。
基本格式:go func()
import (
"fmt"
"math/rand"
)
func Test(ch chan int){
ch <- rand.Int() //隨機數獲取並寫入
fmt.Println("Test")
}
func main() {
chs := make([]chan int , 10) //定義一個包含10個Channel的陣列chs
for i:=0;i<10;i++{
chs[i] = make(chan int)
go Test(chs[i]) //啟動10個Goroutine,對應每一個Goroutin分配一個Channel
}
for _,ch := range chs{
value := <-ch //從通道讀取資料
fmt.Println(value)
}
fmt.Println("main") //因為通道的寫入和讀取都是阻塞的,從而保證了即使沒有鎖,所有的Goroutin執行完後才main才返回。即:main總是在最後輸出的。
}
③通道(Channel)
1>概念
是Go提供的訊息通訊機制。主要用於併發通訊,類似於單雙向資料管道(Pipe),使用者可以通過Channel在兩個或多個Goroutine之間傳遞訊息。
注意:
- 同一時刻只有一個Goroutine能從Channel中接收資料,這就避免了互斥鎖的問題。
- Channel中資料的傳送和接收都是原語操作,不會中斷,只會失敗。
2>宣告和初始化
Channel是引用型別,一個Channel只能傳遞一種型別的值,這個型別需要在宣告Channel時指定。
支援的型別:基本型別、指標、Array、Slice、Map
var chanName chan ElementType
var ch chan int //一個傳遞int型別的Channel。chan為關鍵字。
ch := make(chan int) //用make函式直接宣告
3>資料接收和傳送
ch < - value //通道接收資料。ch表示通道,value表示資料。
value = < - ch //通道傳送資料
注意:
3. 向Channel寫入資料通常會導致程式阻塞,直到有其他Goroutine從這個Channel中讀取資料。
4. 如果Channel中之前沒有寫入資料,那麼從Channel中讀取資料也會導致阻塞,直到Channel中被寫入資料為止。
4>close()
- 只有傳送端才能關閉Channel,只有接收端才能獲得關閉狀態。
- close()呼叫不是必須的,但如果接收端使用range或者迴圈接收資料,就必須呼叫close(),否則報錯:
throw : all goroutines are asleep-deadlock!
5>單向通道
宣告時可以將Chanel制定為單向通道:只能接收或只能傳送。
var chanName chan <- ElementType //只能接收
var chanName <- chan ElementType //只能傳送
6>非同步通道
給Channel設定一個Buffer值,用於持續傳輸大量資料。
在Buffer未寫滿之前,不阻塞傳送操作(即使沒有讀取方,傳送方也不斷寫入資料);
在Buffer未讀完之前,不阻塞接收操作。
ch := make(chan int, 1024) //建立一個大小為1024的int型別Channel。
7>select機制
主要用於解決通道通訊中的多路複用問題。
select語句(類似switch):
select{
case <- chan1: //如果 chan1 成功讀取資料,則進行該case處理語句
case <- chan2:
……
default:
}
select直接檢測case語句,每個case語句必須是一個面向Channel的操作.
只要其中一個case完成,程式就會繼續向下執行。利用這個特性可以可以為Channe實現超時處理功能。
8>超時機制
由於通道的接收是阻塞式的,為了將阻塞式的通訊轉換為非阻塞式,將select機制和超時機制配合使用,以提高系統通訊效率。
在Go語言併發程式設計的通訊過程中,所有錯誤處理都由超時機制來完成。
超時機制一般用來解決通訊死鎖,通常設定一個超時引數,通訊雙方如果在設定的時間內仍然沒處理完成任務,則該處理過程會立即被終止,並返回對應的超時資訊。
Go沒有提供直接的超時處理機制。利用select機制可以實現。
3)網路程式設計
傳統的Socket網路程式設計分為:流式套接字(基於TCP)、資料包套接字(基於UDP)、原始式套接字(基於IP)。
①Dial()
Go語言對socket進行了封裝,無論期望用什麼協議都只需要呼叫Dial函式即可。
支援網路協議:tcp、tcp4、tcp6、udp、udp4、udp6、ip、ip4、ip6。
建立連線:
func Dial ( net, addr string) (Conn, error) //net是網路協議名,addr是IP地址或域名,後面可跟隨埠號。
conn,err := net.Dial ("tcp", "192.168.0.1:5000")
conn,err := net.Dial ("ip4:icmp", "www.baidu.com")
傳送資料:使用conn物件的Write()方法
接收資料:使用conn物件的Read()方法
相關文章
- Go學習總結-go moduleGo
- Vue學習知識點總結Vue
- PG知識點學習總結圖
- 【java學習】java知識點總結Java
- 【建議收藏】Go語言關鍵知識點總結Go
- golang知識總結Golang
- go語言學習-基礎知識Go
- JAVA學習-------第二週知識點總結Java
- EXTJs學習筆記(知識點總結)JS筆記
- go學習鞏固知識點(1)mod 理解 ,中介軟體搭建Go
- GO 學習筆記 《1. 基礎知識》Go筆記
- 知識點總結
- go 學習筆記之初識 go 語言Go筆記
- 總結一下最近的Go學習Go
- 每天一小段總結Go語言知識Go
- linux知識知識點總結Linux
- 第十週學習知識總結
- 執行緒學習知識總結執行緒
- Go語言核心36講(Go語言基礎知識一)--學習筆記Go筆記
- Go語言核心36講(Go語言基礎知識二)--學習筆記Go筆記
- Go語言核心36講(Go語言基礎知識三)--學習筆記Go筆記
- Go語言核心36講(Go語言基礎知識四)--學習筆記Go筆記
- Go語言核心36講(Go語言基礎知識五)--學習筆記Go筆記
- Go語言核心36講(Go語言基礎知識六)--學習筆記Go筆記
- 大資料學習路線指南(最全知識點總結)大資料
- 零基礎學習Java,全方位知識點總結!Java
- 機器學習及深度學習的知識點及面試題總結機器學習深度學習面試題
- Go 之基礎速學 (十二) golang 的一些小總結Golang
- 小白學習Golang(一)Go語言教程Golang
- Golang 基礎學習之Go map操作Golang
- HDFS知識點總結
- MongoDB知識點總結MongoDB
- Java 知識點總結Java
- django知識點總結Django
- jQuery 知識點總結jQuery
- MySQL知識點總結MySql
- HBase知識點總結
- Kafka知識點總結Kafka