golang

golang 环境配置

  • Linux系统
vim /etc/profile
export GOROOT=/usr/local/go
export GOBIN=$GOROOT/bin
export PATH=$PATH:$GOROOT/bin:$GOBIN
go.mod
export GO111MODULE=on
export GOSUMDB=off
export GOPROXY=***
  • Windows系统
go env -w GOPROXY=http://goproxy.***.com
go env -w GO111MOODULE=on
go env -w GOSUMDB=off

golang使用

  • goland函数注释风格设置:File->Settings->Editor->Live Templates
  • 代码同步

GMP模型

  • Goroutine:相当于OS的进程控制块(Process Control Block);它包含:函数执行的指令和参数,任务对象,线程上下文切换,字段保护,和字段的寄存器。
  • M:对应物理线程。
  • P:golang的协程调度器。P的数量可以通过GOMAXPROCS设置。

调度器设计策略

1、复用线程:

  • work stealing机制:当本线程无可运行的Goroutine时,尝试从其他线程绑定的P队列偷取G,而不是消毁线程。
  • hand off机制:当本线程因为Goroutine进行系统调用阻塞时,线程释放绑定的P,把P转移给其它空闲的线程执行。
    2、抢占:在goroutine中要等待一个协程主动让CPU才执行下一个协程;在GO中,一个goroutine最多占用CPU 10ms, 防止其他goroutine被锁死。
    3.利用并行:利用GOMAXPROCS设置P数量,最多有GPMAXPROCS个线程分布在多个CPU上同时执行。
    4.全局G队列:当M执行work stealing从其它P的本地队列中偷不到G时,它可以从全局列队获取G.

runtime

golang 的 runtime 核心功能包括以下内容:协程(goroutine)调度、垃圾回收(GC)、内存分配
使得 golang 可以支持如 pprof、trace、race 的检测

  • 1、内存泄漏:申请了内存,没有及时释放内存。
  • 2、野指针:内存释放后还在使用,导致未定义的行为。
    注:go不支持C++对指针偏移的操作。可以支持GC

一、GO的关键字:

包管理:package、import
变量:var、map、struct、interface、const、type
函数:func、return、defer
循环:if、else、switch、case、fallthought、default、for、break、continue、goto、range
并发:go、chan、select

a := []int{}
copy(a, []int{1, 2, 3})
fmt.Println(a)  // >> [1 2 3]
fmt.Println(append(a, 1))  // >> [1 2 3 1]

b := []int{5}
copy(b, []int{1, 2, 3})
fmt.Println(b)  // >> [1]

c := []int{5, 6, 7, 8}
copy(c, []int{1, 2, 3})
fmt.Println(c) // >> [1, 2, 3, 8]

二、GO的变量类型:

(1)整型
int(默认)、int8、int16、int32、int64、byte
uint、uint8、uint16、uint32、uint64
(2)浮点型:float32、float64(默认)
(3)复数:complex64、complex128(默认)
(4)数组:值拷贝、不同长度和不同类型的数组都是一个新类型
(5)切片:引用
(6)map:引用
(7)复合类型:interface、struct

三、GO的内置函数:append、cap、new、make、copy、len、delete、panic、recover

(1)append:向切片中添加一个或多个值
(2)cap:计算数组和切片已分配的内存空间
(3)new:传入一个结构体名,返回它的一个实例对象的一个引用
(4)make:为切片、map分配空间 ( make([]int, 3) make(map[int]int))
(5)copy:为切片进行值拷贝
(6)len:计算字符串、数组、切片、map当前已使用的空间个数
(7)delete:删除map中的一个key
(8)panic:恐慌、会从当前函数一直往调用该函数的那个函数扩散,直到遇到recover或者是扩散到main函数中
(9)recover:接收恐慌

协程

三个协和交替打印

package main

import (
    "fmt"
    "time"
)

func RunA(count int, ch1, ch2 chan int) {
    for i := 0; i < 10; i++ {
        <-ch1
        fmt.Println(i)
        ch2 <- i
    }
}

func RunB(count int, ch2, ch3 chan int) {
    for i := 0; i < 10; i++ {
        <-ch2
        fmt.Printf("%c\n", 'a'+byte(i))
        ch3 <- i
    }
}

func RunC(count int, ch1, ch3 chan int) {
    for i := 0; i < 10; i++ {
        <-ch3
        fmt.Printf("%c\n", 'A'+byte(i))
        ch1 <- i
    }
}

func main() {
    fmt.Println("Hello World")
    count := 10
    ch1 := make(chan int, 1)
    ch2 := make(chan int, 1)
    ch3 := make(chan int, 1)

    // 启动多个goroutine
    go RunA(count, ch1, ch2)
    go RunB(count, ch2, ch3)
    go RunC(count, ch1, ch3)

    time.Sleep(time.Second * 10)
}


文件操作

package main

import (
    "fmt"
    "os"
)

func main() {
    // 创建一个文件
    file, err := os.Create("test.txt")
    if err != nil {
        fmt.Println("创建文件失败")
        return
    }
    defer file.Close()

    // 写入文件
    _, err = file.WriteString("Hello World")
    if err != nil {
        fmt.Println("写入文件失败")
        return
    }

    // 读取文件
    file, err = os.Open("test.txt")
    if err != nil {
        fmt.Println("打开文件失败")
        return
    }
    defer file.Close()

    content, err := ioutil.ReadAll(file)
    if err != nil {
        fmt.Println("读取文件失败")
        return
    }
    fmt.Println(string(content))
}

字符串操作

package main

import (
    "fmt"
    "strings"
)

func main() {
    s := "Hello World"
    fmt.Println(s[0:5])  // >> Hello
    fmt.Println(s[:5])   // >> Hello
    fmt.Println(s[5:])   // >> World
    fmt.Println(s[5:10]) // >> World

    fmt.Println(strings.ToUpper(s))  // >> HELLO WORLD
    fmt.Println(strings.ToLower(s))  // >> hello world
    fmt.Println(strings.Repeat(s, 3)) // >> Hello WorldHello WorldHello World
}

指针

package main

import "fmt"

func main() {
    var a int = 10
    var b *int = &a
    fmt.Println(*b) // >> 10

    c := 10
    d := &c
    fmt.Println(*d) // >> 10
}

标准库函数

字符串slice处理

package main

import (
    "fmt"
    "sort"
    "strings"
)

func main() {
    s := []string{"Hello", "World"}
    // 判断字符串是否包含子字符串
    fmt.Println(strings.Contains(s[0], "Hello")) // >> true
    fmt.Println(strings.Contains(s[0], "World")) // >> false

    // 字符串的长度和大小
    fmt.Println(len(s))    // >> 2
    fmt.Println(cap(s))    // >> 2
    fmt.Println(len(s[0])) // >> 5

    // 字符串排序
    sort.Slice(s, func(i, j int) bool {
        return s[i] > s[j]  // 降序
    })
    fmt.Println(s) // >> [World Hello]
}

类型转换

package main

import (
    "fmt"
    "strconv"
)

func main() {
    // 字符串转整型
    a := "100"
    b, err := strconv.Atoi(a)
    if err != nil {
        fmt.Println("转换失败")
        return
    }
    fmt.Println(b) // >> 100

    // 字符串转浮点型
    e, err := strconv.ParseFloat(a, 64)
    if err != nil {
        fmt.Println("转换失败")
        return
    }
    fmt.Println(e) // >> 100

    // 字符串转int64
    f, err := strconv.ParseInt(a, 10, 64)
    if err != nil {
        fmt.Println("转换失败")
        return
    }
    fmt.Println(f) // >> 100

    // 整型转字符串
    c := 100
    d := strconv.Itoa(c)
    fmt.Println(d) // >> 100

    // 浮点型转字符串
    g := 100.123
    h := strconv.FormatFloat(g, 'f', 2, 64)
    fmt.Println(h) // >> 100.12

    // int64转字符串
    i := int64(100)
    j := strconv.FormatInt(i, 10)
    fmt.Println(j) // >> 100
}

随机数

package main

import (
    "fmt"
    "math/rand"
    "time"
)

func main() {
    // 生成随机数种子,不然每次都会随机成0
    rand.Seed(time.Now().UnixNano())
    fmt.Println(rand.Intn(100)) // >> 66
    // 生成0到(n-1)的随机整数  int32
    fmt.Println(rand.Int31n(100)) // >> 66
    // 生成0到(n-1)的随机整数  int64
    fmt.Println(rand.Int63n(100)) // >> 66
}

并发

在 sync.WaitGroup(等待组)类型中,每个 sync.WaitGroup 值在内部维护着一个计数,此计数的初始默认值为零。
跟java的CountdownLatch差不多,也是阻塞等待所有任务完成之后再继续执行。
简单使用就是在创建一个任务的时候wg.Add(1),
任务完成的时候使用wg.Done()来将任务减一。
使用wg.Wait()来阻塞等待所有任务完成。

  • (wg *WaitGroup) Add(delta int)
  • (wg *WaitGroup) Done()
  • (wg *WaitGroup) Wait()
package main
import (
    "sync"
)
type httpPkg struct{}
func (httpPkg) Get(url string) {}
var http httpPkg
func main() {
    var wg sync.WaitGroup
    var urls = []string{
        "http://www.golang.org/",
        "http://www.google.com/",
        "http://www.somestupidname.com/",
    }
    for _, url := range urls {
        // Increment the WaitGroup counter.
        wg.Add(1)
        // Launch a goroutine to fetch the URL.
        go func(url string) {
            // Decrement the counter when the goroutine completes.
            defer wg.Done()
            // Fetch the URL.
            http.Get(url)
        }(url)
    }
    // Wait for all HTTP fetches to complete.
    wg.Wait()
}

接口请求读取

package main

import (
    "fmt"
    "io/ioutil"
    "net/http"
)

func main() {
    // 创建一个GET请求
    req, err := http.NewRequest("GET", "https://www.baidu.com", nil)
    if err != nil {
        fmt.Println("创建请求失败")
        return
    }
    // 发送请求
    client := &http.Client{}
    resp, err := client.Do(req)
    if err != nil {
        fmt.Println("发送请求失败")
        return
    }
    defer resp.Body.Close()
    // 读取响应体
    body, err := ioutil.ReadAll(resp.Body)
    if err != nil {
        fmt.Println("读取响应体失败")
        return
    }
    result := struct{
        Code int `json:"code"`
        Data string `json:"data"`
    }{}
    fmt.Println(string(body))
    if err != json.Unmarshal(body, &result) {
        fmt.Println("解析响应失败")
        return
    }
    fmt.Println(result)
}

常用三方工具

    • delve  本地代码调试工具
    • goconvey是一款针对Golang的测试框架,可以管理和运行测试用例,同时提供了丰富的断言函数,并支持很多Web界面特性。
    • goleak 本地排查内存泄露的工具
    • go-wrk  Go接口压测工具
    • golint   代码风格检查
    • revive  代码风格检查,比golint速度更快
    • gocode  代码自动补全工具,可以在vim中使用
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容