GO学习笔记

61 阅读6分钟

用于以后复习GO,GO零基础应该看不懂

package main  
  
import (  
    "bufio"  
    "encoding/json"  
    "flag"  
    "fmt"  
    "io"  
    "io/ioutil"  
    "math/rand"  
    "net"  
    "os"  
    "reflect"  
    "runtime"  
    "strconv"  
    "sync"  
    "time"  
)  
  
//import . "fmt"//导入所有包  
//import otherName "fmt"//取别名  
//import _ "fmt"//忽略此包  
  
//变量、输入、打印  
func base1() {  
    //一个文件夹只能有一个main  
    a := 78 //临时变量  
    a += 800  
    var b, c int //初始值为0  
    var d int = 100  
    e, f, g := 2, 5, 8  
    f, g = g, f  
    const h string = "this_is_const_h"  
    var (  
        i int    = 45  
        j string = "this_is_j"  
    )  
  
    const (  
        //iota在const自动自动增长,如果是同一行,值都一样  
        k = iota //0  
        m = iota //1  
    )  
    {  
        const (  
            //iota在const自动自动增长,如果是同一行,值都一样  
            k = iota //0  
            m        //1  
            n        //2  
            o        //3  
            p        //4  
        )  
    }  
    o := 3 + 4i  
    /*  
        类型:bool(true,false)、byte、rune(4,储存unicode码,可储存中文字符)、  
        int、uint、complex64/128(复数类型)、uintptr(4,指针类型)  
    */  
    n := '中'  
    fmt.Printf("a=%d,c=%d\n\a", a, c)  
    //%T操作变量所属类型  
    // %v自动匹配格式输出  
    fmt.Println(a, "556", b, c, d, e, f, g, h[1:3], i, j, n, o)  
    fmt.Println(real(o), imag(o)) //复数的实部虚部  
    var sa string  
    fmt.Scanf("%s", &sa)  
    fmt.Println(sa)  
    fmt.Scan(&sa)  
    fmt.Println(sa)  
  
    fmt.Printf("%d", int('a')) //类型转换  
    //bool不可以转int  
  
    type newName int  
}  
  
//多返回值,匿名返回  
func f3() (int, int, int) {  
    return 1, 2, 5  
}  
  
//泛型  
func f2[T any](a ...T) (result int) {  
    //两种返回  
    result = 7  
    return 2  
}  
  
//e为不定参数  
func f1(a, b int, c, d string, e ...int) int {  
    f2[int](e...) //e里的所有值都传入f2  
    f2(e[4:]...)  
    return 1  
}  
  
//条件、循环、函数  
func base2() {  
    var a = 10  
    //if语句写法1  
    if a == 12 {  
    } else {  
    }  
  
    //if语句写法2  
    //第一个为赋值,第二个为条件  
    if a = 10; a == 10 {  
    }  
  
    //第一个初始化,第二个条件  
    switch a = 4; a {  
    case 1: //默认不写break  
        fallthrough //执行下面的  
    case 2:  
        fallthrough //执行下面的  
    case 3, 4, 5:  
    default:  
    }  
  
    //for1  
    for i := 0; i < 100; i++ {  
    }  
    //for2  
    str := "hello"  
    for i, s := range str {  
        fmt.Printf("【i=%v,s=%v】", i, s)  
    }  
  
    //for3  
    for i := range str {  
        fmt.Printf("【i=%v,s=%v】", i, str[i])  
    }  
  
    //for3默认为true  
    for {  
        break  
    }  
  
    goto laber1  
  
laber1:  
  
    //函数类型  
    type TF1 func() (int, int, int)  
    var tf TF1  
    tf = f3  
    tf()  
    tf()  
    tf()  
    tf() //tf内的变量依然存在,不会被释放(可用来做自增)  
  
    func() (int, int) { return 1, 2 }() //匿名函数并调用  
    var ff2 = func() {}  
    ff2()  
  
    defer fmt.Println("在函数结束前调用defer") //多个defer,先进后出,堆  
    fmt.Println("序号1")  
  
}  
  
type char byte  
  
func (c char) disp() { //绑定函数  
    fmt.Printf("%c", c)  
}  
  
//接口  
type api interface {  
    //只有声明,没有实现  
    apiFunc()  
}  
type mint int  
  
//接口绑定,只针对自定义数据类型  
func (c char) apiFunc() {  
    fmt.Print(c)  
}  
func (i mint) apiFunc() {  
    fmt.Print(i)  
}  
  
type person struct {  
    Name string  
    age  int  
}  
  
//多重继承,嵌套多个结构体  
type person2 struct {  
    person //匿名继承  
    int  
}  
  
func (p *person) GetAge() int    { return p.age }  
func (p *person) SetAge(age int) { p.age = age }  
  
// NewPerson 构造函数  
func NewPerson(name string) *person { return &person{Name: name} }  
  
//数组、字典、结构体、类  
func base3() {  
    var a = [40]int{8, 5, 9, 6, 15: -1, 20: -89} //部分初始化:下标:值  
    b := [20][30]int{  
        {1, 2, 5},  
        5: {1, 2, 4, 8: -55},  
    }  
    fmt.Println(a)  
    fmt.Println(b)  
    //var b[n]int//不能用n  
    for i := range a {  
        a[i] = i  
    }  
  
    c := [5]int{1, 2, 3}  
    d := [5]int{1, 0, 3}  
    fmt.Println(c == d, c != d) //false true  
  
    //随机数  
    rand.Seed(time.Now().UnixNano()) //设置种子  
    fmt.Println(rand.Intn(100))  
  
    var e = []int{1, 2, 3, 4, 5}  
    f := []int{1, 2, 3, 4, 5}  
    g := e[1:3:4]           //内容[1,3)容量3  
    h := make([]int, 5, 10) //len=5,cap=10,5个0  
    fmt.Println(e, f, g)  
    fmt.Println(len(g), cap(g)) //2 3  
    h = append(h, 4)  
    fmt.Println(h) //[0 0 0 0 0 4]  
    copy(g, h)     //h->g  
  
    m1 := map[byte]string{  
        'a': "hello",  
        'b': "world",  
    }  
    m1['c'] = "C++"  
  
    fmt.Println(m1)  
  
    for key, val := range m1 {  
        fmt.Println(key, val)  
    }  
  
    val, ok := m1['d'] //是否存在键  
    fmt.Println(val, ok)  
    delete(m1, 'c')  
  
    //首字母大写结构体(类)是public,小写private,属性方法也一样  
    type ST1 struct {  
        v1   string  
        v2   int  
        next *ST1  
    }  
  
    var st1 = ST1{"444", 8, new(ST1)}  
    var st2 = &ST1{v1: "444", v2: 8}  
  
    fmt.Println(st1, st2, st1.v2, st2.v1, (*st2).v1) //st2.v1与(*st2).v1等价  
    fmt.Println(st1 == *st2, st1 != *st2)            //false true  
  
    var st3 ST1  
    st3 = st1  
    fmt.Println(st3)  
  
    type ST2 struct {  
        v2  int  
        ST1 //继承ST1中的属性  
        v3  int  
    }  
  
    st21 := ST2{500, ST1{"sss", 44, new(ST1)}, 40}  
    st21.v1 = "hello struck"  
    st21.ST1 = ST1{"hej", 78, new(ST1)}  
    st21.ST1.v2 = 45  
    fmt.Printf("%+v", st21)  
  
    ch1 := char('a')  
    ch1.disp()     //方法绑定  
    cf := ch1.disp //方法值  
    cf()  
    cf1 := (*char).disp //方法表达式1  
    cf1(&ch1)  
    cf2 := char.disp //方法表达式2  
    cf2(ch1)  
  
    var aa [4]interface{}  
    aa[1] = 1234  
    aa[2] = "asdfg"  
    aa[3] = [5]int{1, 2, 5, 85}  
    fmt.Println("\n\naa>>>", aa)  
  
    var bb int  
    bb = aa[1].(int) //断言,aa[]是空接口类型,不能直接赋值给bb,需要断言  
    fmt.Println(bb)  
  
    {  
        a := NewPerson("hello")  
        a.SetAge(58)  
        var b person2  
        b.person = *a  
        b.int = 10 //直接访问匿名字段  
        fmt.Println(a)  
        fmt.Println(b)  
    }  
  
}  
  
type Monster struct {  
    //序列化后Name->monster_name  
    Name string `json:"monster_name"`  
    Age  int    `json:"monster_age"`  
}  
  
func (v Monster) print() {  
    fmt.Println("MonsterPrint-->\n", "Name>>>", v.Name, "\nAge>>>", v.Age)  
}  
  
type myAny interface{}  
  
//func anys2T[T any]()  
  
func base4() {  
    //文件操作File的方法(位于os包中)  
    //Read、ReadAt、Write、WriteString、WriteAt、Seek、Sync、Close  
    fileName := "E:\\编程测试文件\\1005.txt"  
    //fileOpenError := "file open error"  
    readByBufio := func(fileName string) string {  
        f, e := os.Open(fileName)  
  
        fmt.Println(f, e)  
        if e != nil {  
            fmt.Println("file open error")  
            return ""  
        }  
        //带缓冲的读取(4096),适用于大文件读取  
        reader := bufio.NewReader(f)  
        fmt.Println(reader)  
        i := 0  
        var text string = ""  
        for {  
            //读取,读到换行结束  
            s, e := reader.ReadString('\n')  
            //读到末尾  
            if e == io.EOF {  
                break  
            }  
            text += s  
            fmt.Print("L", i, ">>>", s)  
            i++  
        }  
        err := f.Close()  
        if err != nil {  
            return ""  
        }  
        return text  
    }  
  
    readByBufio(fileName)  
  
    //一次性读取,适用于小文件读取  
    //text为[]byte类型  
    readByIoutil := func(fileName string) string {  
        f, e := os.Open(fileName)  
  
        fmt.Println(f, e)  
        if e != nil {  
            fmt.Println("file open error")  
            return ""  
        }  
        text, e := ioutil.ReadFile(fileName) //无需close  
  
        if e != nil {  
            fmt.Println("file open error")  
            return ""  
        } else {  
            fmt.Println(text)  
            fmt.Println(string(text))  
        }  
        e = f.Close()  
        return string(text)  
    }  
  
    readByIoutil(fileName)  
  
    fileWriteByBufio := func(fileName string, flag int, text []string) {  
        //文件读写  
        //路径,模式,权限  
        f, e := os.OpenFile(fileName, flag, 4)  
        if e != nil {  
            fmt.Println("file open error")  
        } else {  
            w := bufio.NewWriter(f)  
            //写入缓存  
            for i, t := range text {  
                //写入缓存  
                w.WriteString(t)  
                i++  
            }  
            //写入磁盘  
            //w.Flush()  
        }  
        //带缓存的write  
        e = f.Close()  
    }  
    fileWriteByBufio(fileName, os.O_WRONLY|os.O_CREATE|os.O_APPEND, []string{"hello1\n", "hello2\n"})  
    readByBufio(fileName)  
  
    pathExists := func(fileName string) (bool, error) {  
        //e为nil时存在,为os.IsNotExist(e)为true时不存在,其他类型不确定  
        _, e := os.Stat(fileName)  
        if e == nil {  
            return true, nil  
        }  
        if os.IsExist(e) == true {  
            return false, nil  
        }  
        return false, e  
    }  
    pathExists(fileName)  
  
    {  
        //获取命令行参数os.Args  
        fmt.Println(os.Args)  
        var (  
            user string  
            pwd  string  
            host string  
            port int  
        )  
        //自动解析参数值 mysql -u root -pwd 123 ...  
        flag.StringVar(&user, "u", "", "用户名默认为空")  
        flag.StringVar(&pwd, "pwd", "", "密码默认为空")  
        flag.StringVar(&host, "h", "127.0.0.1", "主机名默认为127.0.0.1")  
        flag.IntVar(&port, "port", 3306, "用户名默认为3306")  
  
        flag.Parse() //开始转换  
  
    }  
  
    {  
        //myAny=interface{}  
        //return->[]string|[][]byte  
        toJson := func(maps []myAny) [][]byte { //411  
            var datat [][]byte  
            // 序列化map  
            for _, m := range maps {  
                data, _ := json.Marshal(m)  
                datat = append(datat, data)  
            }  
            return datat  
        }  
  
        a := map[string]myAny{"name": "namemmmm", "age": 888}  
        s := person{"nameppp", 45} //private类型不参加序列化  
  
        m := Monster{"nameMonster", 777}  
        jsonbyt := toJson([]myAny{s, a, m})  
        fmt.Println("jsonbyt>>>")  
        for _, i := range jsonbyt {  
            fmt.Println(string(i))  
        }  
  
        fmt.Println((jsonbyt))  
  
        fromJson := func(js [][]byte) []myAny {  
            var T []myAny  
            for _, i := range js {  
                var t myAny  
                json.Unmarshal(i, &t)  
                T = append(T, t)  
            }  
            return T  
        }  
  
        fmt.Println("fromJson>>>")  
        result := fromJson(jsonbyt)  
        fmt.Println(result)  
  
        aa := toJson([]myAny{s, s, s})  
        bb := fromJson(aa)  
        fmt.Println("fromJson>>>bb>>")  
  
        fmt.Println(bb)  
        //p := bb[0].(person)  
        //fmt.Println(p)  
  
        rVal := reflect.ValueOf(myAny(m)) //any->reflect.ValueOf  
        rTyp := reflect.TypeOf(myAny(m))  
        fmt.Println("rVal>>>", rVal, rTyp)  
        iVal := rVal.Interface() //reflect.ValueOf->any  
        v := iVal.(Monster)      //any->struct  
        fmt.Println(v, iVal.(Monster).Name)  
  
        {  
            var a int64 = 4  
            rVal := reflect.ValueOf(myAny(a)) //any->reflect.ValueOf  
            //rVal.SetInt(88)                     //改变rVal//error  
            rpVal := reflect.ValueOf(myAny(&a)) //any->reflect.ValueOf  
            rpVal.Elem().SetInt(99)             //改变a  
            fmt.Println(rVal, rpVal, a)  
        }  
  
        num := rVal.NumField() //获取结构体有多少个字段  
        for i := 0; i < num; i++ {  
            tarVal := rTyp.Field(i).Tag.Get("json") //反序列化的字段  
            fmt.Println(i, ">>>", rVal.Field(i), ">>>", tarVal)  
        }  
        m.print()  
        //numM := rVal.NumMethod() //获取结构体有多少个字段  
        //rVal.Method(0).Call(nil)  
        //reflect.ValueOf(&m).Method(0).Call(nil)  
        println("\n")  
    }  
}  
  
func base5() {  
    { /*  
            A.go存放被测试的函数package A  
            X_test.go存放测试用例(可以有多个_test)package A  
                func TestY(t *testing.T){//可以有多个函数  
                    if ...  
                    t.Fatalf("%v",)//打印错误的信息  
                    t.Logf("")//打印正确信息  
                }  
        */  
    }  
  
    {  
        var memo = make(map[int]string)  
        var lock sync.Mutex  
  
        goroutinef := func(n int) {  
            //捕获函数发出的异常,在协程中可以方防止协程错误导致崩溃  
            defer func() {  
                if err := recover(); err != nil {  
                    fmt.Println(">>>", err)  
                }  
            }()  
  
            var s string = ""  
            for i := 0; i <= n; i++ {  
                s += strconv.Itoa(i)  
            }  
            lock.Lock()  
            memo[n] = s  
            lock.Unlock()  
  
            if n == 0 {  
                fmt.Println("n==", 1/n)  
            }  
        }  
        for i := 0; i <= 200; i++ {  
            go goroutinef(i) //开启协程,如果主线程执行完毕了,协程也会跟着退出  
        }  
        time.Sleep(time.Second * 1)  
        lock.Lock()  
        for i := 0; i <= 200; i++ {  
            fmt.Println(i, "\t>>>", memo[i])  
        }  
        lock.Unlock()  
  
        var n int  
        n = runtime.NumCPU()  
        fmt.Println("CPU个数", n)  
        runtime.GOMAXPROCS(n - 1) //设置可同时执行的最大cpu个数max=n,go1.8以后的版本默认默认运行在多核上  
  
    }  
  
    {  
        intChan := make(chan int, 10)         //管道声明,可存10个int  
        var c <-chan int = make(chan int, 10) //read only  
        //var c chan<- int = make(chan int, 10) //write only  
  
        intChan <- 10 //写入数据  
        intChan <- 10  
        intChan <- 10  
        intChan <- 10  
        intChan <- 10  
        intChan <- 10  
        fmt.Println(<-intChan) //取出数据  
        //传统方法会发生阻塞  
        //for {  
        //    v, ok := <-intChan  
        //    fmt.Println(v, ok)  
        //    if !ok {  
        //        break  
        //    }  
        //}  
  
        for {  
            flag := false  
            select {  
            case v := <-intChan:  
                fmt.Println("intChan", v)  
            case v := <-c:  
                fmt.Println("c", v)  
            default:  
                flag = true  
                fmt.Println("all empty")  
                //可使用label  
                break  
            }  
            if flag {  
                break  
            }  
        }  
  
        close(intChan) //关闭通道  
        //遍历管道要关闭管道  
        for i := range intChan {  
            fmt.Println(i)  
        }  
        writeChan := make(chan int, 20)  
        readChan := make(chan bool, 1)  
        writeChan <- 10  
        writeChan <- 10  
        writeChan <- 10  
        //write  
        go func(w chan int) {  
            for i := 0; i < 50; i++ {  
                w <- i  
                //time.Sleep(time.Millisecond * 100)  
                fmt.Println("write>>>", i)  
            }  
            close(w)  
        }(writeChan)  
        //read  
        go func(r chan bool, w chan int) {  
            for {  
                v, ok := <-w  
                time.Sleep(time.Millisecond * 100)  
                //fmt.Println("ok>>>", ok)  
                if !ok {  
                    break  
                }  
                fmt.Println("read>>>", v)  
            }  
            r <- true  
            close(r)  
        }(readChan, writeChan)  
  
        for {  
            _, ok := <-readChan  
            if !ok {  
                break  
            }  
            //fmt.Println("read>>>", v)  
        }  
  
    }  
  
}  
func network() {  
    ipport := "127.0.0.1:8888"  
  
    server := func(ipport string) {  
        //read client input  
        process := func(conn net.Conn) {  
            defer conn.Close()  
  
            for {  
                fmt.Println("server>>>waiting client input>>>", conn.RemoteAddr().String())  
                buf := make([]byte, 1024)  
                n, e := conn.Read(buf)  
                if e == io.EOF {  
                    fmt.Println("server>>>client quited", e)  
                    return  
                }  
                fmt.Println(">>>server>>>read>>>", string(buf[:n]))  
            }  
        }  
  
        fmt.Println("server >>>listening")  
        l, e := net.Listen("tcp", ipport)  
        if e != nil {  
            fmt.Println("server>>>fail listening")  
            return  
        }  
        for {  
  
            fmt.Println("server>>>waiting connection")  
            c, e := l.Accept()  
            if e != nil {  
                fmt.Println("server>>>accept error")  
            }  
            fmt.Println("server>>>accept succ ip>>>", c.RemoteAddr().String())  
  
            go process(c)  
        }  
        defer l.Close()  
        fmt.Println("server>>>succ listening>>>", l)  
    }  
    //fmt.Println("<<<server>>> enter ip<<<")  
    //fmt.Scan(&ipport)  
    go server(ipport)  
    time.Sleep(time.Millisecond * 100)  
  
    client := func(ipport string) {  
        c, e := net.Dial("tcp", ipport)  
        if e != nil {  
            fmt.Println("client >>>dial error")  
            return  
        }  
        fmt.Println("client >>>conn succ>>>", c)  
        fmt.Println("<<<client >>>write something<<<")  
        reader := bufio.NewReader(os.Stdin)  
        line, e := reader.ReadString('\n')  
        if e != nil {  
            fmt.Println("client >>>NewReader error")  
        }  
  
        fmt.Println("client >>>write succ")  
        n, e := c.Write([]byte(line))  
        fmt.Println("client >>>write succ bytes=", n)  
        if e != nil {  
            fmt.Println("client >>>Write  error")  
        }  
    }  
    //fmt.Println("<<<client>>> enter ip")  
    //fmt.Scan(&ipport)  
    go client(ipport)  
  
    for {  
    }  
}  
  
func redis() {  
    /*  
                    D:\ProgramFiles\Redis-x64-3.0.504  
                    redis-server.exe redis.windows.conf  
  
                    //把redis服务作为一个注册为系统服务在后台运行  
                    redis-server --service-install redis.windows.conf --service-name redis  
  
                    启动redis服务(设置自启)  
                    win + R 然后输入services.msc回车。打开服务找到redis服务  
                    启动redis并把启动类型修改为自动(如果不是自动的话)  
  
  
        //cmd 登录  
             .\redis-cli -h 127.0.0.1 -p 6379  
            AUTH -[username] [password]  
  
    */  
  
}  
func main() {  
    //base1()//变量、输入、打印  
    //base2()//条件、循环、函数  
    //base3()//数组、字典、结构体、类  
    //base4() //文件、cmd、json、反射  
    //base5() //单元测试、协程管道  
    //network()//不全  
    redis()  
}