Go语言基础 1 2 3 4 5 6 package main import "fmt" func main () { fmt.Println("hello world" ) }
当标识符(包括常量、变量、类型、函数名、结构字段等等)以一个大写字母开头,如Group1,那么使用这种形式的标识符的对象就可以被外部包的代码所使用(客户端程序需要先导入这个包) 这个被称为导出(面向对象语言中的public);标识符如果以小写字母开头,则对包外是不可见的,但是他们在整个包的内部是可见并且可用的(面向对象语言中的protected)
1 2 go语言特性要求变量声明后和包引入后必须使用,这是个很好的特性能够避免一些低级错误. 全局变量是允许声明但不使用的
需要注意的是 { 不能单独放在一行,所以以下代码在运行时会产生错误
1 2 3 4 5 6 package mainimport "fmt" func main () { fmt.Println("Hello, World!" ) }
行分隔符
1 2 3 fmt.Println("Hello, World!" ) fmt.Println("菜鸟教程:runoob.com" )
注释
数据类型 1 2 3 4 5 6 7 8 9 10 11 12 1 布尔值2 数字类型3 字符串类型4 派生类型(a )指针类型 (b )数组类型 (c)结构化类型 (d)Channel类型 (e)函数类型 (f)切片类型 (g)接口类型 (h)map类型
数字类型
uint8 无符号8位整型(0-255)
uint16 无符号16位整型(0-65535)
uint32 无符号32位整型(0-4294967295)
uint64 无符号64位整型(0-18446744073709551615)
int8 有符号8位整型(-128-127)
int16 有符号16位整型(-32768-32767)
int32 有符号32位整型(-2147483648 - 2147483647)
int64 有符号 64 位整型 (-9223372036854775808-9223372036854775807)
浮点型
float32 IEEE-754 32位浮点型数
float64 IEEE-754 64位浮点型数
complex64 32 位实数和虚数
complex128 64 位实数和虚数
其他数字类型
byte 类似 uint8
rune 类似 int32
uint 32 或 64 位
int 与 uint 一样大小
uintptr 无符号整型,用于存放一个指针
声明变量 第一种
1 2 var v_name v_type v_name = value
零值就是变量没有做初始化时系统默认设置的值
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 package mainimport "fmt" func main () { var a = "RUNOOB" fmt.Println(a) var b int fmt.Println(b) var c bool fmt.Println(c) }
数值类型(包括complex64/128)为0
布尔类型为false
字符串””
以下几种类型为nil
1 2 3 4 5 6 var a *int var a []int var a map [string ] int var a chan int var a func (string ) int var a error
1 2 3 4 5 6 7 8 9 10 11 package mainimport "fmt" func main () { var i int var f float64 var b bool var s string fmt.Printf("%v %v %v %q\n" , i, f, b, s) }
第二种
根据值自行判定变量类型
1 2 3 4 5 6 7 package mainimport "fmt" func main () { var d = true fmt.Println(d) }
第三种
1 2 3 var intVal int intVal := 1 intVal, intVal1 := 1 ,2
多变量声明 1 2 3 4 5 6 7 8 9 10 11 12 var vname1, vname2, vname3 type vname1, vname2, vname3 = v1, v2, v3 var vname1, vname2, vname3 = v1, v2 ,v3 vname1, vname2, vname3 := v1, v2, v3 var { vname1 v_type1 vname2 v_type2 }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 package mainvar x, y int var ( a int b bool ) var c, d int = 1 , 2 var e, f = 123 , "hello" func main () { g, h := 123 , "hello" println (x, y, a, b, c, d, e, f, g, h) }
1 0 0 0 false 1 2 123 hello 123 hello
值类型和引用类型 所有像int、float、bool和string这些基本类型都属于值类型,使用这些类型的变量直接指向存在内存中的值
当使用等于=将一个变量的值赋值给另一个变量时,如:j=i,实际上是在内存中将i的值进行了拷贝
1 可以通过&i 来获取i 的内存地址,例如:oxf840000040(每次地址都可能不一样),
简短形式
a和b的类型(int和bool)将由编译器自动推断
如果在相同的代码块中,不可以再次对相同名称的变量使用初始化声明
1 2 3 4 5 var a int a = 2 fmt.Print(a)
常量 常量是一个简单值得标识符,在程序运行时,不会被修改的量
常量的数据类型只可以是布尔型,数字型(整数型、浮点型和复数)和字符串型
const identifier [type] = value
可以省略类型说明符[type],因为编译器可以根据变量的值来推断其类型
显式类定义:const b string = “abc”
隐式类型定义:const b = “abc”
1 2 3 4 5 const LENGTH int = 10 fmt.Print(LENGTH) const A, B, C = 1 , false , "str" print (A, B, C)
常量可以使用len(),cap(),unsafe.Sizeof()函数计算表达式的值
1 2 3 4 5 6 7 8 9 10 package mainimport "unsafe" const ( a = "abc" b = len (a) c = unsafe.Sizeof(a) ) func main () { println (a, b, c) }
iota 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 func main () { const ( a = iota b c d = 1 e = iota f g = "k" h i j k ) print (a, b, c, d, e, f, g, h, i, j, k) }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 package main import "fmt" const ( i=1 <<iota j=3 <<iota k l ) func main() { fmt.Println("i=" ,i ) fmt.Println("j=" ,j ) fmt.Println("k=" ,k ) fmt.Println("l=" ,l ) }
Go语言运算符 1 2 3 4 5 6 算术运算符 关系运算符 逻辑运算符 位运算符 赋值运算符 其他运算符
函数 1 2 3 func function _name( [parameter list ] ) [return_types ] { 函数体 }
函数定义解析:
func:函数由func开始声明
function_name:函数名称,函数名称和参数列表一起构成了函数签名
parameter list:参数列表,参数就像一个占位符,当函数被调用时,你可以将值传递给参数,参数列表指定的是参数类型、顺序、及参数的个数。参数是可选的,也就是说参数不可以包含参数
return_types:返回类型,函数返回一列值。return_types是该列值的数据类型,有些功能不需要返回值,所以return_types不是必须的
函数体:函数定义的代码集合
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 package mainimport "fmt" func max (num1 int , num2 int ) int { var result int if num1 > num2 { result = num1 } else { return num2 } return result } func main () { i := max(1 , 2 ) fmt.Print(i) }
函数返回多个值 Go函数可以返回多个值
1 2 3 4 5 6 7 8 9 10 package mainimport "fmt" func swap (x, y string ) (string , string ) { return y, x } func main () { a, b := swap("Google" , "Runoob" ) fmt.Println(a, b) }
一般情况下,Go语言使用的是值传递,即在调用过程中不会影响到实际参数
变量作用域 局部变量
1 2 3 4 5 6 7 8 9 package mainimport "fmt" func main () { var a, b, c int a = 1 b = 2 c = a + b fmt.Print(c) }
全局变量
在函数体外声明的变量称之为全局变量,全局变量可以在整个包甚至在外部包使用
全局变量可以在任何函数中使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 package mainimport "fmt" var g int func main () { var a, b int a = 10 b = 20 g = a + b fmt.Printf("结果: a = %d, b = %d and g = %d\n" , a, b, g) }
Go 语言程序中全局变量与局部变量名称可以相同,但是函数内的局部变量会被优先考虑。实例如下:
1 2 3 4 5 6 7 8 9 package mainimport "fmt" var g int = 20 func main () { var g int = 10 fmt.Printf ("结果: g = %d\n" , g) }
Go语言数组
声明数组
1 var variable _n ame [SIZE] variable _ type
1 var balance [10] float32
初始化数据
1 var balance = [5 ]float32 {1000.0 , 2.0 , 3.4 , 7.0 , 50.0 }
如果忽略[]中的数字不设置数组大小,Go语言会根据元素的个数来设置数组的大小
1 var balance = [...]float32 {1000.0 , 2.0 , 3.4 , 7.0 , 50.0 }
该实例与上面的实例是一样的,虽然没有设置数组的大小
访问数组元素
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 package mainimport "fmt" func main () { var n [10 ]int var i, j int for i = 0 ; i < 10 ; i++ { n[i] = i + 100 } for j = 0 ; j < 10 ; j++ { fmt.Printf("Element[%d] = %d\n" , j, n[j]) } }
指针 1 2 3 4 5 6 package mainimport "fmt" func main () { var a int = 1 fmt.Printf("变量的地址: %x" , &a) }
指针申明
1 2 var ip *int var fp *float32
指针使用流程
定义指针变量
为指针变量赋值
访问指针变量中指向地址的值
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 package mainimport "fmt" func main () { var a int = 20 var ip *int ip = &a fmt.Printf("a 变量的地址是:%x\n" , &a) fmt.Printf("ip 变量存储的指针地址:%x\n" , ip) fmt.Printf("ip 变量的值:%d\n" , *ip) }
1 2 3 a 变量的地址是:c0000 a2058 ip 变量存储的指针地址:c0000 a2058 ip 变量的值:20
空指针 当一个指针被定义后没有分配到任何变量,它的值位nil
nil指针也成为空指针
nil在概念上和其他语言的null,None,nil,NULL一样,都指代零值或空值
一个指针变量通常缩写位ptr
1 2 3 4 5 6 7 8 9 10 11 package main import "fmt" func main() { var ptr *int fmt.Printf ("ptr 的值为 : %x\n" , ptr ) fmt.Print (ptr == nil ) }
结构体 Go语言中数组可以存储同一类型的数据,但在结构体中我们可以认为不同项定义不同的数据类型
结构体是由一系列具有相同类型或不同类型的数据构成的数据集合
结构体格式如下:
1 2 3 4 5 6 type struct_variable_type struct { member definition member definition ... member definition }
一旦定义了结构体类型,它就能用于变量的声明,语法格式如下:
1 2 3 variable_name := structure_variable_type {value1, value2...valuen} 或 variable_name := structure_variable_type { key1: value1, key2: value2..., keyn: valuen}
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 package mainimport "fmt" type Books struct { title string author string subject string book_id int } func main () { fmt.Println(Books{"Go 语言" , "www.runoob.com" , "Go 语言教程" , 6495407 }) fmt.Println(Books{title: "Go 语言" , author: "www.runoob.com" , subject: "Go 语言教程" , book_id: 6495407 }) fmt.Println(Books{title: "Go 语言" , author: "www.runoob.com" })
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 package mainimport "fmt" type Student struct { name string age int } func main () { student := Student{ name: "gaoming" , age: 0 , } fmt.Print(student) fmt.Print(student.age) fmt.Print(student.name) }
结构体作为函数参数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 package mainimport "fmt" type Books struct { title string author string subject string book_id int } func main () { var Book1 Books var Book2 Books Book1.title = "Go 语言" Book1.author = "www.runoob.com" Book1.subject = "Go 语言教程" Book1.book_id = 6495407 Book2.title = "Python 教程" Book2.author = "www.runoob.com" Book2.subject = "Python 语言教程" Book2.book_id = 6495700 printBook(Book1) printBook(Book2) } func printBook ( book Books ) { fmt.Printf( "Book title : %s\n" , book.title) fmt.Printf( "Book author : %s\n" , book.author) fmt.Printf( "Book subject : %s\n" , book.subject) fmt.Printf( "Book book_id : %d\n" , book.book_id) }
结构体指针
结构体指针定义
1 var struct_pointer *Books
存放地址
使用结构体指针访问结构体成员,使用”.”操作符
语言切片
Go语言切片是对数组的抽象
Go数组的长度不可改变,在特定场景下这样的集合不太适用,Go中提供了一种灵活、功能强悍的内置类型切片(”动态数组”),与数组相比切片的长度是不固定的,可以追加元素,在追加时可能使切片的容量增大
定义切片
切片不需要说明长度
或使用make()函数来创建切片
1 2 var slice1 []type = make ([]type , len )slice1 := make ([]type , len )
也可以指定容量,其中capacity为可选参数
1 make ([]T, length, capacity)
这里 len 是数组的长度并且也是切片的初始长度。
切片初始化
直接初始化切片,[]表示是切片类型,{1,2,3}初始化值依次是1,2,3,其cap=len=3
初始化切片s,是数组arr的引用
1 s := arr[startIndex:endIndex]
将arr中从下标startIndex到endIndex-1下的元素创建为一个新的切片
默认startIndex时将表示从arr的第一个元素开始
默认endIndex时将表示一直到arr的最后一个元素
1 s1 := s[startIndex:end Index]
通过切片s初始化切片s1
通过内置函数make()初始化切片s,[]int标识为其元素类型为int的切片
len()和cap()函数
切片是可索引的,并且可以由len()方法获取长度
切片提供了计算容量的方法cap()可以测量切片最长可以达到多少
1 2 3 4 5 6 7 8 9 10 11 12 package mainimport "fmt" func main () { var numbers = make ([]int ,3 ,5 ) printSlice(numbers) } func printSlice (x []int ) { fmt.Printf("len=%d cap=%d slice=%v\n" ,len (x),cap (x),x) }
1 len =3 cap=5 slice=[0 0 0 ]
空(nil)切片
1 2 3 4 5 6 7 8 9 10 11 12 13 package mainimport "fmt" func main () { var numbers []int printSlice(numbers) if (numbers == nil ){ fmt.Printf("切片是空的" ) } } func printSlice (x []int ) { fmt.Printf("len=%d cap=%d slice=%v\n" ,len (x),cap (x),x) }
1 2 len =0 cap =0 slice=[]切片是空的
切片截取
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 package mainimport "fmt" func main () { numbers := []int {0 ,1 ,2 ,3 ,4 ,5 ,6 ,7 ,8 } printSlice(numbers) fmt.Println("numbers ==" , numbers) fmt.Println("numbers[1:4] ==" , numbers[1 :4 ]) fmt.Println("numbers[:3] ==" , numbers[:3 ]) fmt.Println("numbers[4:] ==" , numbers[4 :]) numbers1 := make ([]int ,0 ,5 ) printSlice(numbers1) number2 := numbers[:2 ] printSlice(number2) number3 := numbers[2 :5 ] printSlice(number3) } func printSlice (x []int ) { fmt.Printf("len=%d cap=%d slice=%v\n" ,len (x),cap (x),x) }
1 2 3 4 5 6 7 8 len =9 cap=9 slice=[0 1 2 3 4 5 6 7 8 ]numbers == [0 1 2 3 4 5 6 7 8] numbers [1 :4 ] == [1 2 3] numbers [:3 ] == [0 1 2] numbers [4 :] == [4 5 6 7 8] len =0 cap=5 slice=[]len =2 cap=9 slice=[0 1 ]len =3 cap=7 slice=[2 3 4 ]
append()和copy()函数
如果想增加切片的容量,必须创建一个新的更大的切片并把原分片的内容都拷贝过来
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 package mainimport "fmt" func main () { var numbers []int printSlice(numbers) numbers = append (numbers, 0 ) printSlice(numbers) numbers = append (numbers, 1 ) printSlice(numbers) numbers = append (numbers, 2 ,3 ,4 ) printSlice(numbers) numbers1 := make ([]int , len (numbers), (cap (numbers))*2 ) copy (numbers1,numbers) printSlice(numbers1) } func printSlice (x []int ) { fmt.Printf("len=%d cap=%d slice=%v\n" ,len (x),cap (x),x) }
1 2 3 4 5 len =0 cap=0 slice=[]len =1 cap=1 slice=[0 ]len =2 cap=2 slice=[0 1 ]len =5 cap=6 slice=[0 1 2 3 4 ]len =5 cap=12 slice=[0 1 2 3 4 ]
Go语言范围 go语言中range关键字用于for循环迭代数组(array),切片(slice)、通道(channel)或集合(map)的元素
在数组和切片中返回元素的索引和索引对应的值,在集合中返回key-value对
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 package mainimport "fmt" func main () { nums := []int {2 , 3 , 4 } sum := 0 for _, num := range nums { sum += num } fmt.Println("sum:" , sum) for i, num := range nums { if num == 3 { fmt.Println("index:" , i) } } kvs := map [string ]string {"a" : "apple" , "b" : "banana" } for k, v := range kvs { fmt.Printf("%s->%s\n" , k, v) } for i, c := range "go" { fmt.Println(i, c) } }
1 2 3 4 5 6 sum : 9 index : 1 a -> appleb -> banana0 103 1 111
Map集合
Map是一种无序的键值对的集合,Map最重要的一点是通过key来快速检索数据,key类似于索引,指向数据的值
Map是一种集合,所以我们可以向迭代数组和切片那样迭代它,不过,Map是无序的,我们无法决定它的返回顺序,这是因为Map是使用了Hash表来实现的
定义Map
可以使用内建函数make也可以使用map关键字来定义Map
1 2 3 4 5 var map_variable map [key_data_type]value_data_typemap_variable := make (map [key_data_type]value_data_type)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 package mainimport "fmt" func main () { var countryCapitalMap map [string ]string countryCapitalMap = make (map [string ]string ) countryCapitalMap["France" ] = "巴黎" countryCapitalMap["Italy" ] = "罗马" countryCapitalMap["Japan" ] = "东京" countryCapitalMap["India" ] = "新德里" for country := range countryCapitalMap { fmt.Println(country, "首都是" , countryCapitalMap[country]) } capital, ok := countryCapitalMap["American" ] if ok { fmt.Println("American 的首都是" , capital) } else { fmt.Println("American 的首都不存在" ) } }
delete()函数
delete()函数用于删除集合的元素,参数为map和其对应的key
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 package mainimport "fmt" func main () { countryCapitalMap := map [string ]string {"France" : "Paris" , "Italy" : "Rome" , "Japan" : "Tokyo" , "India" : "New delhi" } fmt.Println("原始地图" ) for country := range countryCapitalMap { fmt.Println(country, "首都是" , countryCapitalMap[country]) } delete (countryCapitalMap, "France" ) fmt.Println("法国条目被删除" ) for country := range countryCapitalMap { fmt.Println(country, "首都是" , countryCapitalMap[country]) } }
1 2 3 4 5 6 7 8 9 原始地图 France 首都是 Paris Italy 首都是 Rome Japan 首都是 Tokyo India 首都是 New delhi 法国条目被删除 Italy 首都是 Rome Japan 首都是 Tokyo India 首都是 New delhi
Go语言递归函数 递归,就是在运行过程中调用自己
1 2 3 4 5 6 7 func recursion () { recursion() } func main () { recursion() }
Go 语言支持递归。但我们在使用递归时,开发者需要设置退出条件,否则递归将陷入无限循环中。
递归函数对于解决数学上的问题是非常有用的,就像计算阶乘,生成斐波那契数列等\
斐波那契
以下实例通过Go语言的递归函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 package mainimport "fmt" func Fac (n int ) int { if n == 1 { return 1 } if n == 2 { return 2 } return Fac(n-1 ) + Fac(n-2 ) } func main () { fac := Fac(8 ) fmt.Println(fac) }
Go语言类型转换 1 类型转换用于将一种数据类型的变量转换为另外一种类型的变量。Go 语言类型转换基本格式如下:
type_name 为类型,expression 为表达式。
1 2 3 4 5 6 7 8 9 package mainimport "fmt" func main () { var sum int = 17 var count int = 5 var mean float32 mean = float32 (sum)/float32 (count) fmt.Printf("mean 的值为: %f\n" ,mean) }
语言接口 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 type interface_name interface { method_name1 [return_type] method_name2 [return_type] method_name3 [return_type] ... method_namen [return_type] } type struct_name struct { } func (struct_name_variable struct_name) method_name1 () [return_type ] { } ... func (struct_name_variable struct_name) method_namen () [return_type ] { }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 package mainimport ( "fmt" ) type Phone interface { call() } type NokiaPhone struct {} func (nokiaPhone NokiaPhone) call () { fmt.Println("I am Nokia, I can call you!" ) } type IPhone struct {} func (iPhone IPhone) call () { fmt.Println("I am iPhone, I can call you!" ) } func main () { var phone Phone phone = new (NokiaPhone) phone.call() phone = new (IPhone) phone.call() }
Go错误处理
go语言通过内置的错误接口,提供了非常简单的错误处理机制
error类型是一个接口类型,这是它的定义
1 2 3 type error interface { Error() string }
我们可以在编码中通过实现error接口类型来生成错误信息
函数通常在最后的返回值中返回错误信息,使用errors.New可返回一个错误信息
1 2 3 4 5 6 func Sqrt (f float64 ) (float64 , error) { if f < 0 { return 0 , errors.New("math: square root of negative number" ) } }
Go并发 Go语言支持并发,只需要通过go关键字来开启goroutine即可
goroutine是轻量级线程,goroutine的调度是由GoLang运行时进行管理的
goroutine语法格式
开启一个新的goroutine
Go允许使用go语句开启一个新的运行期线程,即goroutine,以一个不同的,新建的goroutine来执行一个函数。同一个程序中所有goroutine共享一个地址空间
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 package mainimport ( "fmt" "time" ) func say (s string ) { for i := 0 ; i < 5 ; i++ { time.Sleep(100 * time.Millisecond) fmt.Println(s) } } func main () { go say("world" ) say("hello" ) }
通道 通道是用来传递数据的一个数据结构
通道可以用于两个goroutine之间通过传递一个指定类型的值来同步运行和通讯
操作符<-用于指定通道的方向,发送或接收
如果未指定方向,则为双向通道
1 2 ch <- v // 把V发送到通道ch v := <-ch // 从 ch 接收数据 并把值赋给 v
声明一个通道很简单,我们使用chan关键字即可,通道在使用前必须先创建
注意
默认情况下,通道是不带缓冲区的,发送端发送数据,同时必须有接收端相应的接收数据
以下实例通过两个goroutine来计算数字之和,在goroutine完成计算之后,他会计算两个结果的和
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 package mainimport "fmt" func sum (s []int , c chan int ) { sum := 0 for _, v := range s { sum += v } c <- sum } func main () { s := []int {7 , 2 , 8 , -9 , 4 , 0 } c := make (chan int ) go sum(s[:len (s)/2 ], c) go sum(s[len (s)/2 :], c) x, y := <-c, <-c fmt.Println(x, y, x+y) }
通道缓冲区 通道可以设置缓冲区,通过make的第二个参数指定缓冲区的大小
1 ch := make (chan int , 100 )
带缓冲区的通道允许发送端的数据发送和接收端的数据获取处于异步状态,就是说发送端发送的数据可以放在缓冲区里面,可以等待接收端去获取数据,而不是立刻需要接收端去获取数据
不过由于缓冲区的大小是有限的,所以还是必须有接收端来接收数据的,否则缓冲区一满,数据发送端就无法再发送数据了
注意
如果通道是不带缓冲的,发送方会阻塞直到接收方从通道中接收了值,如果通道带缓冲,发送方则会阻塞直到发送的值被拷贝到缓冲区内,如果缓冲区已满,则意味着需要等待直到某个接收方获取到一个值。接收方在有值可以接收之前会一直阻塞。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 package mainimport "fmt" func main () { ch := make (chan int , 2 ) ch <- 1 ch <- 2 fmt.Println(<-ch) fmt.Println(<-ch) }
Go遍历通道与关闭通道 go通过range关键字来实现遍历读取到的数据,类似于与数组或切片。格式如下
如果通道接收不到数据后ok就为false,这时通道就可以使用close()函数来关闭
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 package mainimport "fmt" func fibonacci (n int , c chan int ) { x, y := 0 , 1 for i := 0 ; i < n; i++ { c <- x x, y = y, x+y } close (c) } func main () { c := make (chan int , 10 ) go fibonacci(cap (c), c) for i := range c { fmt.Println(i) } }