Skip to content

Latest commit

 

History

History
365 lines (289 loc) · 5.06 KB

Chapter01Intro.md

File metadata and controls

365 lines (289 loc) · 5.06 KB

Golang Introduction

Go Features

Some Features:

  1. gc
    1. 只需要new分配内存,不需要释放
    2. 内存自动回收,再也不需要开发人员管理内存
  2. 天然并发
    1. 从语言层面支持并发,非常简单
    2. goroutine,轻量级线程(本质是协程映射到物理线程上,但比操作系统的线程轻量),创建成千上万个goroutine成为可能(而创建成千上万个线程,程序会被OS kill),能够充分利用多核CPU
    3. 基于CSP(Communicating Sequential Process)模型实现
  3. channel
    1. 多个goroutine之间通过channel进行通信, channel类似Unix/Linux下的pipe
    2. channel支持任何数据类型
  4. 多返回值

example: simple example

package main

import "fmt"

func add(a int, b int) int {
	var sum int
	sum = a + b
	return sum
}

func main() {
	var s int
	s = add(100, 10)
	// 如果变量定义不使用,不能通过编译
	fmt.Println("Result=", s)
}

example: goroutine

run in terminal: go run hello.go test.go
run in vscode: F5

./
    hello.go
    test.go
// test.go
package main

import "fmt"

func testGoroutine(a int) {
	fmt.Println(a)
}
// hello.go, 两个文件同属一个package: main
package main

import (
	"fmt"
	"time"
)

func add(a int, b int) int {
	var sum int
	sum = a + b
	return sum
}

func main() {
	var s int
	s = add(100, 10)
	fmt.Println("Result=", s)

	// 并发打印
	for i := 0; i < 20; i++ {
		go testGoroutine(i)
	}
	// 主rouinte等待 3s
	time.Sleep(time.Second * 3)
}

example: 多核CPU占用100%

// test.go
package main

func testInfLoop(a int) {
	for {

	}
}
// hello.go
package main

import (
	"time"
)

func main() {
	for i := 0; i < 20; i++ {
		go testInfLoop(i)
	}
	// 主rouinte等待
	time.Sleep(time.Second * 60)
}

example: channel

全局变量虽然可以作为goroutine的数据交互但不推荐

package main

import "fmt"

func testChannel() {
	// make分配内存空间
	// channel中放的是int, 容量是3
	pipe := make(chan int, 3)
	// 放数据进channel
	pipe <- 1
	pipe <- 11
	pipe <- 111

	// use data in pipe
	a := <-pipe
	b := <-pipe
	pipe <- 6
	fmt.Println(len(pipe)) // 2
	fmt.Println(a, b)      //1 11
}

func main() {
	testChannel()
}
var pipe1 chan int
pipe1 = make(chan int, 3)
// 两者等价
pipe2 := make(chan int, 3)

var a int
a = <- pipe2
// 两者等价
a := <- pipe2

example: channel 阻塞

package main

import (
	"fmt"
	"time"
)

func testChannel() {
	pipe := make(chan int, 3)
	pipe <- 1
	pipe <- 11
	pipe <- 111
	pipe <- 1111 // 阻塞

	fmt.Println(len(pipe))
}

func main() {
	println("start goroutine")
	go testChannel()
	println("end goroutine")
	time.Sleep(10 * time.Second)
}

example: 主routine从次routine中获取数据,并且channel是全局变量(不推荐)

package main

import "fmt"

var pipe chan int

func add(a int, b int) {
	sum := a + b
	pipe <- sum
}

func main() {
	pipe = make(chan int, 1)
	go add(100, 200)
	b := <-pipe // wait here
	fmt.Println(b)
}

example: 主routine从次routine中获取数据

package main

import "fmt"

func add(a int, b int, p chan int) {
	sum := a + b
	p <- sum
}

func main() {
	var pipe chan int
	pipe = make(chan int, 1)
	go add(100, 200, pipe) // pipe本质是指针
	b := <-pipe
	fmt.Println(b)
}

example: 多返回值

package main

import "fmt"

func calc(a int, b int) (int, int) {
	sum := a + b
	avg := sum / 2
	return sum, avg
}

func do(a int, b int) (float32, int) {
	c := float32(a) / float32(b)
	// c : a/b
	d := a * b
	return c, d
}

func main() {
	sum, avg := calc(100, 200)
	fmt.Println(sum, avg) // 300 150
	c, _ := do(100, 200)
	fmt.Println(c) // 0.5
}

Go package

  • 和python一样,把相同功能的代码放到一个目录,称之为包
  • 包可以被其他包引用

应用程序入口:

  • 必须是package main, 表明代码所在的package
  • 必须是func main()
  • 文件名不一定是main.go
# golang标准package目录
# GOPATH
./
    src/
        mypackage/
            calc/
                add.go
                sub.go
            main/
                main.go
// add.go
package calc

// Add is doing adding
func Add(a int, b int) int {
	return a + b
}
//sub.go
package calc

// Sub is doing subtract
// 大写的Sub才是public的函数
func Sub(a int, b int) int {
	return a - b
}
// main.go
package main

import (
	"fmt"
	"mypackage/calc"
)

func main() {
	sum := calc.Add(100, 200)
	fmt.Println(sum)
	sub := calc.Sub(100, 200)
	fmt.Println(sub)
}

build: go build mypackage/main

example: goroutine package

src/
    myroutine/
        calc/
            add.go
        main/
            main.go
// add.go
package calc

// Add is a gorouine method
func Add(a int, b int, p chan int) {
	c := a + b
	p <- c
}
// main.go
package main

import (
	"fmt"
	"myroutine/calc"
)

func main() {
	pipe := make(chan int, 3)
	go calc.Add(100, 200, pipe)
	sum := <-pipe
	fmt.Println(sum)
}