Golang

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

37个保留字

Constants: true false iota nil

Types: int int8 int16 int32 int64
uint uint8 uint16 uint32 uint64 uintptr
float32 float64 complex128 complex64
bool byte rune string error

functions: make len cap new append copy close delete complex real imag panic recover

声明

var a int
const PI 3.1415
type 
func

目录结构

  • src :源码文件
  • bin:二进制编译文件
  • pkg:包文件

内置类型

  1. 值类型

    bool,string,array,int,uint….

  2. 引用类型

    slice –序列数组

    map – 映射

    chan – 管道

内置函数

append          -- 用来追加元素到数组、slice中,返回修改后的数组、slice
close           -- 主要用来关闭channel
delete            --map中删除key对应的value
panic            -- 停止常规的goroutine  (panicrecover:用来做错误处理)
recover         -- 允许程序定义goroutine的panic动作
real            -- 返回complex的实部   (complexreal imag:用于创建和操作复数)
imag            -- 返回complex的虚部
make            -- 用来分配内存,返回Type本身(只能应用于slice, map, channel)
new                -- 用来分配内存,主要用来分配值类型,比如intstruct。返回指向Type的指针
cap                -- capacity是容量的意思,用于返回某个类型的最大容量(只能用于切片和 mapcopy            -- 用于复制和连接slice,返回复制的数目
len                -- 来求长度,比如string、array、slice、map、channel ,返回长度
printprintln     -- 底层打印函数,在部署环境中建议使用 fmt 包

内置接口error

type error interface { //只要实现了Error()函数,返回值为String的都实现了err接口

          Error()    String

  }

init函数与main的异同

相同点:
    两个函数在定义时不能有任何的参数和返回值,且Go程序自动调用。
不同点:
    init可以应用于任意包中,且可以重复定义多个。
    main函数只能用于main包中,且只能定义一个。

go的命令

go env用于打印Go语言的环境信息。

go run命令可以编译并运行命令源码文件。

go get可以根据要求和实际情况从互联网上下载或更新指定的代码包及其依赖包,并对它们进行编译和安装。

go build命令用于编译我们指定的源码文件或代码包以及它们的依赖包。

go install用于编译并安装指定的代码包及它们的依赖包。

go clean命令会删除掉执行其它命令时产生的一些文件和目录。

go doc命令可以打印附于Go语言程序实体上的文档。我们可以通过把程序实体的标识符作为该命令的参数来达到查看其文档的目的。

go test命令用于对Go语言编写的程序进行测试。

go list命令的作用是列出指定的代码包的信息。

go fix会把指定代码包的所有Go语言源码文件中的旧版本代码修正为新版本的代码。

go vet是一个用于检查Go语言源码中静态错误的简单工具。

go tool pprof命令来交互式的访问概要文件的内容。

go 的语言范围range ☞ 数组之和

func main(){
    nums := []int{1,12,3,4} // 创建一个数组
    sum := 0 // 定义一个计数器
    for _, num := range nums {
        sum += num
    }
    fmt.Println("sum:",sum)
}

Map

无序键值对的集合,同python的列表,Map使用hash 表实现

可以使用内建函数 make 或 关键字 map 定义 map

var map_variable map[key_data_type]value_data_type
i := make(map[key_data_type]vaule_data_type)
// 熟练后使用第二种

package main
import "fmt"
func main(){
    var onemap map[string]int
    onemap = make(map[string]int) // map 必须初始化,否则会报错
    onemap["France"] = 1
    onemap["china"] = 0
    onemap["India"] = 2
    for num := range onemap{
        fmt.Println(num, onemap[num])
    }
}

delete(onemap,"India")

test

package main
import (
    "fmt"
    "math/rand"
)

func main(){
    soucemap := make(map[string]int, 100)
    // 写入80 个键值对
    for i :=0;i<80; i++{
        key := fmt.Sprintf("stu%02d",i)
        value := rand.Intn(100) // 100的随机数
        soucemap[key] = value
    } 
    // 按照keys 的顺序配列
    keys := make([]string,0,100) // 对切片操作,map无法操作
    for k := range soucemap{
        keys = append(keys,k)
    }
    sort.Strings(keys)
    for _,key := range keys{
        fmt.Println(key,soucemap(key))
    }
    
}

go 指针

package main
import "fmt"

func main(){
    a := 10
    fmt.Println("变量的地址: %x\n", &a)
}

/* & 指向目标地址
声明一个字符指针 var ptr *string
使用指针访问值,*(&a)
当一个指针被定义后没有分配到任何变量时,它的值为 nil
*/

go 结构体和接口

type struct_variable_type struct {
    member defintion
    ...
    member defintion
}
variable_name := strure_variable_type{key1:varlue1,key2:varlue2,...}

type interface_name interface {
   method_name1 [return_type]
   method_name2 [return_type]
   method_name3 [return_type]
   ...
   method_namen [return_type]
}
 // demo:
package main

import "fmt"

type Phone interface {
	call()
	call2()
}

type Phone1 struct {
	id    int
	name  string
	title string
}

func (test Phone1) call() {
	fmt.Println("first return function data:", Phone1{id: 1, name: "bob"})

}
func (test Phone1) call2() {
	fmt.Println("second return function data:", Phone1{id: 2, name: "kang"})

}

type Phone2 struct {
	id   int
	name string
	fun  int
}

func (test Phone2) call() {
	fmt.Println("first return function data:", Phone2{id: 4, name: "bob2"})

}
func (test Phone2) call2() {
	fmt.Println("second return function data:", Phone2{id: 3, name: "test"})

}

func main() {
	var phone Phone
	phone = new(Phone1)
	phone.call()
	phone.call2()

	phone = new(Phone2)
	phone.call()
	phone.call2()
	fmt.Println("vim-go")
}

go 切片(Slice)

var identifier []type
slice1 := make([]type, len)

slice 有三个参数 type, len, cap (最长可以达到多少)
slice := make([]int, 10,21)

slice 的函数:append(),copy()

go 的递归

func res(){ // 调用自身
    res()
}
func main(){
    res()
}

package main
import "fmt"
func factorial(n uint64)(result uint64){
    if (n>0){
        result = n*factorial(n-1)
        return result
    }
    return 1
}
func main(){
    var i int = 15
    fmt.Printf("%d 的阶乘是 %d\n",i,factorial(uint64(i)))
}

go 类型转换

var sum int = 17
var count int = 5
var mean float32
mean = float32(sum)/float32(count)
// go 不支持隐式转换 ,即 mean = count 会报错,mean = float23(count)

go 错误处理

error 类型是一个接口类型
type error interface {
    Error() string
}

// demo
func sqrt(f float64) (float64, error){
    if f<0{
        return 0, errors.New("math: square root of negative number")
    }
}

go 并发

package main
import (
	"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")
}

hello与world 是无固定先后顺序的,因为这是两个 goroutine 执行;

channel(信道)

两个goroutine 之间传递一个指定类型的值来同步运行和通讯,操作符 <- 用于指定通道方向

ch := make(chan int) // 创建通道
// 发送端发送数据,必须有接收端相应的接收数据,否则接收端会一直等待

//demo
func sum(s []int,c chan int){
    sum := 0
    for _,v:=range s{
        sum += v
    }
    c <- sum // sum 发送到通道c
}
func main(){
    s := []int{1,2,3,4,5}
    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)
}

通道缓冲区

ch := make(chan int, 100)