包含标签 golang 的文章

基于共享变量的并发

一、 竞争条件 多个 goroutine 并发访问同一变量时,如果存在对该变量的写操作。就会发生竞争。 go 的口头禅:不要使用共享数据来通信;使用通信来共享数据。 避免竞争方法 方法一、不要去写共享变量 方法二、避免从多个goroutine访问变量 方法三、使用互斥锁 二、 sync.Mutex互斥锁 二元信号量 一个只能为0和1信号量叫做二元信号量 var ( sema = make(chan struct{}, 1) // a binary semaphore guarding balance balance int ) func Deposit(amount int) { sema <- struct{}{} // acquire token balance = balance + amount <-sema // release token } func Balance() int { sema <- struct{}{} // acquire token b := balance <-sema // release token return b } sync 包中的 Mutex 类似二元信号量 import "sync" var ( mu sync.……

阅读全文

Golang复合类型

简述 基本类型是Go语言世界的原子,复合类型则是分子。 数组 数组是固定长度的序列。因此,其很少直接使用。 与C语言数组特性类似。 var a [3]int //其中[3]int为数组类型 fmt.Println(a[0]) fmt.Println(a[len(a) - 1]) var b [3]int = [3]int{1, 2, 3} var c [3]int = [3]int{1, 2} var d = [...]int{1, 2, 3, 4} // len = 4 q := [...]int{1, 2} //指定一个索引和对应值列表的方式初始化 type Currency int const ( USD Currency = iota // 美元 EUR // 欧元 GBP // 英镑 RMB // 人民币 ) symbol := [...]string{USD: "$", EUR: "€", GBP: "£", RMB: "¥"} fmt.……

阅读全文

Golang基础数据类型

整型 一般整型 int8 int16 int32 int64 uint8 uint16 uint32 uint64 分别对应8、16、32、64bit的数 特别的整型 Unicode字符rune类型是和int32等价的类型,通常用于表示一个Unicode码点。因此rune和int32可以互换使用。 byte类型等价于uint8类型,byte用于强调数据的原始性。 uintptr用来存放指针,多用于底层编程。 int和int32大小相同,但是,是两个不同的类型。 取模的结果总是与被取模数的符号相同 fmt.Println(5%3) //2 fmt.Println(5%-3) //2 fmt.Println(-5%3) //-2 fmt.Println(-5%-3) //-2 符点数 float32、float64 通常应该优先使用float64类型,因为float32类型的累计计算误差很容易扩散。 复数 complex64、complex128 var x complex128 = complex(1, 2) // 1+2i var y complex128 = complex(3, 4) // 3+4i fmt.Println(x*y) // "(-5+10i)" fmt.Println(real(x*y)) // "-5" //取实部 fmt.Println(imag(x*y)) // "10" //取虚部 布尔型 true/false // btoi returns 1 if b is true and 0 if false.……

阅读全文

Golang 程序结构

关键字 go中含有25个关键字 break default func interface select case defer go map struct chan else goto package switch const fallthrough if range type continue for import return var 此外,还有大约30多个预定义的名字 内建常量: true false iota nil 内建类型: int int8 int16 int32 int64 uint uint8 uint16 uint32 uint64 uintptr float32 float64 complex128 complex64 bool byte rune string error 内建函数: make len cap new append copy close delete complex real imag panic recover 名字大小写 大写的名字表明是可导出的,即可被其它包访问,如fmt包中的Println 小写的名字只能在包内使用 名字长度 一般名字的长度是没有限制的。 Go提倡短小的名称,如表示索引,定义为i,而不是index等 当作用域范围较大或生命周期较长的变量,采用较长的名字可能会更好。 声明 主要有4种类型的声明语句: var(变量) var 变量名字 类型 = 表达式……

阅读全文

Goroutines和Channels

CSP: “顺序通信进程”(communicating sequential processes)或被简称为CSP。 CSP是一种现代的并发编程模型,在这种编程模型中值会在不同的运行实例(goroutine)中传递。 一、Goroutines 定义:在GO中,每个并发的执行单元被称为一个goroutine go语句: 在函数或方法前加上关键字go,就形成了go语句。go语句使函数或方法在新建的goroutine中执行。 程序启动时,主函数(main函数)会在main goroutine中执行。当main goroutine退出时,所有其它goroutine都会退出。 f() // call f(); wait for it to return go f() // create a new goroutine that calls f(); don't wait func main() { l, err := net.Listen("tcp", "192.168.0.1:8000") if err != nil { log.Fatal(err) } for { conn, err := l.Accept() if err != nil { log.Print(err) continue } go handleConn(conn) } } 二、Channels channel 是 goroutines之间通信的机制 通过make来创建一个channel 与map类似,channel也是能底层数据结构的引用,作为函数参数传递时,是传递的引用。 channel的零值为nil。 channel之间可以用 == 进行比较。 一个channel有发送和接收两个操作,都是通信行为。 发送将一个值从一个goroutine发送到另一个接收该值的goroutine。 发送和接收都使用 <- 运算符号,发送时,<-分割channel和要发送的值。接收时,<-放在channel之前。 在关闭的channel上发送数据会引起panic, 但可以接收数据,如果被关闭的channel中没有数据,则得到零值。 ch <- x // a send statement y := <-ch // a receive expression in an assignment statement <-ch // a receive statement; result is discarded close(ch) // close channel 三、不带缓冲的channel ch = make(chan int) // unbuffered channel ch = make(chan int, 0) // unbuffered channel ch = make(chan int, 3) // buffered channel with capacity 3 在无缓存的channel上进行收发操作,将会导致此goroutine阻塞,直到有另一个goroutine对该通道进行发收操作。 无缓存的channel上的收发,导致两个goroutine进行一次同步操作。所以,无缓存channel也叫同步channel。 当我们说x事件既不是在y事件之前发生也不是在y事件之后发生,我们就说x事件和y事件是并发的。 func main() { conn, err := net.……

阅读全文