go基础个人学习笔记

GOLANG

语言结构
package main
import (
    "fmt"
)
func main(){
    fmt.Print("Hello World!")
}


// 执行
go run main.go
// 使用 go build 生成二进制文件
go build main.go
./main
go module
go env
go env -w GO111MODULE=on
go env -w GOPROXY=
	https://mirrors.aliyun.com/goproxy/ 
	https://goproxy.cn,direct
GOSUMDB	//检验代码包是否完整
GONOSUMDB
GONOPROXY
GOPRIVATE
	// 若第三方库为私有库,该仓库无需通过 proxy 下载

流程:
	0. 开启 GO111MODULE、设置 GOPROXY 等
	1. 创建项目文件夹 project/
	2. 创建模块文件夹 module/
	3. 在 module/ 使用 	go mod init 名字		生成 go.mod 文件

常用指令:
	go mod init
	go mod tidy	//更新依赖文件
	go mod download
	go mod vendr	//将依赖转移至本地的 vendor 文件
	go mod verify	//校验依赖
	go mod edit	//手动修改依赖文件
导包
import "test"
/*
1. ==> test.go
2. ==> test.go 中的 import "test2"
3. ==> test2.go 中的没有 import, var、const等全局声明, init()
4. ==> test.go 中的全局声明
5. ==> 层层往上推
*/
// 由此,init() 优先级高于 main,类似数据库连接、环境变量等可以放在 init

// -------------------------------- 包别名 ------------------------------- //
//import 导入的包未使用会报错
//可使用 
import(
    _ "lib1"
)
//会调用 lib1 的 init(), 且不使用不会报错
变量
var a int       a = 10
var b = 10
c := 10
var d,e,f = 1,2,3
// " := " 不可以在已声明变量使用
// 变量声明必须使用
常量
const a int = 10

// iota 特殊常量, 可以认为是一个可以被编译器修改的常量,
// 只能在 const 中使用
const (
	a = itoa // 初始化 1 
    b		 // itoa + 1
    c		 // itoa + 1
    d = "ha" // itoa + 1
    e
    f = 100
    g
    h = itoa // 恢复计数 itoa + 1
    i
)
// 结果
0 1 2 ha ha 100 100 7 8
条件语句
// --------------------- if --------------------- //
var a int
fmt.scanf("%d", &a)
if a>10 {
    fmt.Println("a > 10")
}else if a <= 10 {
    fmt.Println("a <= 10")
}

// --------------------- switch --------------------- //
switch i := b.(type) {
    case nil :
    	fmt.Println("b is nil")
    case int :
    	fmt.Println("b is nil")
    default :
    	fmt.Println("b is string")
}

// --------------------- fallthrough 强制执行后面的 case 语句 --------------------- //
switch i := 10 {
    case 5 :
    	fmt.Println("b is 5")
    case 10 :
    	fmt.Println("b is 10")
    	fallthrough
    default 15:
    	fmt.Println("b is 15")
}
// b is 10 
// b is 15 


// --------------------- select --------------------- //
// 类似 switch,但只能用于管道 channel
// 每个 case 必须是一个通道操作,要么是发送要么是接收.
// 任意一个通道可以运行,select 就执行;没有则执行 default,没有 default 则阻塞
package main
import "fmt"
func main(){
    ch1 := make(chan string)
    ch2 := make(chan string)
    go func{
        for {
            ch1 <- "ch1" 
        }
    }()
    go func{
        for {
            ch2 <- "ch2" 
        }
    }()
    for {
        select{
            case msg1 := <-ch1:
                fmt.Println(msg1)
            case msg2 := <-ch2:
                fmt.Println(msg1)
            default :
                fmt.Println("no message received")
        }
    }
}
循环
// ------------------- 迭代 ------------------- //
for key, value := rang smap {
    
}
// ------------------- 正常 ------------------- //
for i := 10; i > 0; i-- {
    
}

// ------------------- 类 while ------------------- //
i := 20
for i > 10{
    
    i--
}

// ------------------- break 		select 也可以使用 return ------------------- //
// 可使用 标记
re:
    for i:=10;i>8;i--{
        break re
    }
函数
func func_name()(ret_type1, ret_type2){
    
}

// -------------------------- //

func max(num1 ,num2 int) int {
    // deal
    return max_value
}
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
// 在 GO 中,函数的参数传递都是值传递

数组
// 固定长度、特定类型
// slice 切片,可改变长度的数组
var a [3]int = [3]int{1,2,3} 
// or
a : = [3]int{1,2,3}
r := [...]int{99:-1}	// 赋值第 99 个为 -1,其余为 0
// 根据初始化值确定长度
a := [...]int{1,2,3,4,5}	//此时长度为 5

// 类型包含长度,如 [3]int 和 [4]int 不是同一种类型
切片
// 其底层引用了一个数组对象,一个 slice 由指针、长度和容量
// 指针:指向第一个 slice 元素对应的底层数组元素的地址
// 因此,即便是值传递,也能修改切片内容

var slice1 []type = make([]type, len, capacity)

slice1 := make([]type, len, capacity)

s := []int{1,2,3}

// ----------------- append() ----------------- //
// 当 append 超过切片容量时,其会将原来的元素复制到新的位置,2 倍扩大自己的容量,此时对于 append 的 slice 的修改不会影响底层数组
// https://zhuanlan.zhihu.com/p/61121325


Map
// 无序
// --------------------- 声明 --------------------- //
var myMap1 map[string]int //此时 myMap1 为 nil

myMap1 = make(map[string]int, 10)

myMap1 := make(map[string]int)

myMap1 := map[string]in{
    "one":1,
    "two":2
}

// --------------------- 使用 --------------------- //
// 添加、修改
myMap2["china"] = "Beijing"
// 删除
delete(myMap2, china)
// 遍历
for _, value := range myMap2{
    fmt.Println(value)
}


// 作为参数传递时为引用传递
结构体
// 声明一种数据类型 type
type myint int

type Book struct{
    name string
    price string
}

func (this Book) GetName() string {
    return this.name
}

// ----------------------- 关于结构体传参拷贝 ----------------------- //
func (this Book) SetName(newName string){
    // this 是调用该方法的对象的一个副本(拷贝)
    // 这里的 SetName 不会影响原对象 name 的属性
    // 可以加入指针,实现引用
    // 谁调用 SetName,this 指向谁
}
// 这里的 this 仅仅是个形参变量,可以是任何值,不同于 C、C++ 等的 this 关键字
// 如:
func (this *Book) SetName(newName string){
    // 这里 this 是引用, SetName 会影响原对象 name 的属性
}
// ----------------------- 关于结构体传参拷贝 ----------------------- //

func changeBook(book *Book){
    book.price = book.price + 1
}


// 访问
var book = Book{name: "", price:10}
fmt.Println(book.name)
changeBook(&book)
SetName(book)

// -------------------------------- 关于继承(组合) -------------------------------- //
// go 里面没有继承的说法,称为 “组合”
type Human struct{
    name string
    age int
}
type superHuman struct{
    Human
    fly bool
}
// 这里 superHuman 可以说是继承于 Human,但实际为组合
// 赋值
bianfuxia := superHuman{Human{"bianfu", 100}, true}
// 或者
var bianfuxia superHuman
bianfuxia.name = "bianfu"
bianfuxia.age = 100
bianfuxia.fly = true


// ------------------------ tag/json ------------------------ //
type movie struct{
    title string `info:"标题", doc:"test"`
    price string `info:价格`
}
// 获取标签
func gettagcontent(arg interface()) string {
    tCollect := reflect.TypeOf(arg).Elem()
    for i:=0; i < tCollect.NumFiled(); i++ {
        fmt.Print( tCollect.Filed(i).Tag.Get("info") )
    }
}


// 属性绑定标签, key-value 格式,且不一定只有一个
// 当需要使用 json 时
type movie struct{
    Title string `json:"title"`
    Price string `json:"price"`
}
movie1 := movie{...}
// 结构体 ---> json
jsonStr, err := json.Marshal(movie1)

// json ---> 结构体
movie2 := movie{}
err = json.Unmarshal(jsonStr, &movie2)
多态
// 类实现 interface 所有方法即可
type action interface{
    sleep()
    GetColor() string
    SetColor(color string)
}

type animal struct{
    name string
    color string
}

func (this *animal) sleep(){
    
}
func (this *animal) GetColor() string {
    return this.color
}

func (this *animal) SetColor(color string){
    this.color = color
}
vat cat action
cat = &animal{"cat"}
cat.Setcolor("black")
万能类型
//interface
func animal(arg interface{}){
	//此时 arg 就是万能类型
    value, ok := arg.(string)
    //判断是否为 string 类型
}

// golang 中变量内部构造,type + value
// 其中 type 分为 static type 和 concrete type,合称 pair
// int、string . . .           具体类型,结构体 . . . 
defer
// 结束前指向 defer 后的内容
// 多个 defer,遵循先进后出,栈
// 可与错误处理结合 panic、recover
func defaultRecover(){
    if err := recover(); err != nil{
        fmt.Println("recover in func DefaultRecover")
		fmt.Println(fmt.Sprintf("%T %v", err, err))
    }
}

func main(){
    defer defaultRecover()
    fmt.Println("main func")
}
// defer 和 return 同一函数中, return 先于 defer
反射
reflect.TypeOf()	// 返回类型信息 reflect.Type
// 可通过 reflect.Type 的 string 方法返回类型的字符串表示 
// a := reflect.TypeOf(value)
// typeGet := a.sting()

reflect.VlaueOf()	// 返回值

// 下面的 fmt 中的 %T 用的就是 reflect.TypeOf()
fmt.Printf("%T\n", a)
Goroutine
// main 为主协程,所有的新开协程都是基于 main

func newTask(){
    i := 1
    for{
        i++
        fmt.Println("newTask i = %d\n", i)
        time.Sleep(1 * time.Second)
    }
}

func main(){
    i := 1
    go newTask()
    for{
        i++
        fmt.Println("main i = %d\n", i)
        time.Sleep(1 * time.Second)
    }
}

// newTask i = 1
// main i = 1
// newTask i = 1
// main i = 1
// ...
若将 main 中的 for 去掉,可能结果
// newTask i = 1
因为 main 执行完毕就会退出,顺带结束 newTask()


// sync.WaitGroup 等待执行完毕
var wg sync.WaitGroup
func newTask_wg(){
    defer wg.Done()	//任务完成时 -1
}
func main(){
    wg.Add(1)	// 创建任务时 +1
    go newTask_wg()
    wg.Wait()	// 阻塞等待所有任务完成
}

channel
// goroutine 中数据交流用 channel
// 创建
chan := make(channel int)
// 写入管道
chan <- 122
// 读取管道并判断是否为空
value,ok <- chan


// ------------------------- 无缓冲 channel ------------------------- //
// 读、写都会阻塞
test_value := 10
chan <- test_value	// chan 未被读取会一直阻塞在此
<- chan	// chan 未被写入会一直阻塞在此


// ------------------------- 有缓冲 channel ------------------------- //
ch := make(chan int, 3)
// 通过 len(ch)、cap(ch) 查看


// ------------------------- 关闭 channel ------------------------- //
// 除非确定没有数据读写,不然不用关闭

func timeDown(ch chan int){
    for i:=0;i<10;i++{
        ch <- i
        if i==5{
            close(ch)
            return
        }
    }
}

func main(){
    var ch = make(chan int)
    go timeDown(ch)
    for{
        if value, ok := <- ch;ok{
            fmt.Print("value = %d", value)
        }else{
            break
        }
    }
    fmt.Print("channel closed ! \n")
}
channel 和 range 以及 select 的结合使用
// range 从通道不断地读数据
for data := range ch{
    fmt.Println(data)
}

// select 监控多个 chan 的状态
for{
    select {
    case <-ch:
        fmt.Println("ch 可读")    
    case ch<-:
    	fmt.Println("ch 可写")
    }
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值