zoukankan      html  css  js  c++  java
  • go语言开发入门

    go语言开发入门

    每个Go程序包含一个名为main的包以及其main函数,在初始化后,程序从main开始执行,避免引入不使用的包(编译不通过)

    基础语法

    基本数据类型

    bool, byte
    int,int8,int16,int32,int64
    uint8,uint16,uint32,uint64 
    float32,float64(没有float类型)
    string
    

    变量赋值

    var a
    a = 12
    a := 12
    a,b :=12,23
    

    常量赋值

    const(
      a = iota
      b
    )
    

    循环只有 for

    for i:=0;i<10;i++{
       do Something...
    }
    
    for{
       //相当于while(true){}
    }
    
    for _,v:= range list{
       //range用法返回list数组或者列表的k,v两个值(k数组索引从0开始,v值)
       fmt.Print("%s", v)
    }
    

    选择 ifswitch

    a := 1
    b := 1
    if a+b > 2 {
       // 注:if(条件不带括号,且左大括号与if保持同行)
    }
    
    • 学习一门语言学会循环

    完整demo 大白加大白等于白胖胖.求大,白,胖各是数字多少?

    package main
    
    import (
      "fmt"
      "strconv"
    )
    
    /* 大白加大白等于白胖胖.求大,白,胖各是数字多少? */
    func main() {
        for d := 1; d < 10; d++ {
            for b := 1; b < 10; b++ {
                for p := 1; p < 10; p++ {
                    daBai, _ := strconv.Atoi(strconv.Itoa(d) + strconv.Itoa(b))
                    // fmt.Println("大白", daBai)
                    baiPangPang, _ := strconv.Atoi(strconv.Itoa(b) + strconv.Itoa(p) + strconv.Itoa(p))
                    // fmt.Println("白胖胖", baiPangPang)
                    if daBai+daBai == baiPangPang {
                        fmt.Println("-------------------大 白 胖--------------------")
                        fmt.Printf("大 = %d, 白 = %d, 胖 = %d
    ", d, b, p)
                        fmt.Println("白胖胖: ", baiPangPang)
                    }
                }
            }
        }
    }
    

    数据(array)与切片(slice)

    数组声明:ArrayType = "[" ArrayLength "]" ElementType .

    var a [32] int
    var b [3][5] int
    

    (1)数组是值类型。将一个数组赋值给另一个,会拷贝所有的元素.

    (2) 如果你给函数传递一个数组,其将收到一个数组的拷贝,而不是它的指针.

    (3)数组的大小是其类型的一部分,类型[10]int和[20]int是不同的。数组长度在声明后,就不可更改.

    切片声明:SliceType = "[" "]" ElementType .

    var a []int
    

    (1)没有初始化的slice为nil.

    (2)切片(slice)对数组进行封装,实际上,切片可以看成大小可以动态变化的数组.

    (3)Go中大多数的数组编程都是通过切片完成,而不是简单数组.

    一般来说,有两种方式来初始化切片:

    //通过数组方式
    var myArray [10]int = [10]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
    var mySlice []int = myArray[:5]
    //make方式
    make([]T, length, capacity)
    

    Channel

    • Goroutine和channel是Go在“并发”方面两个核心feature。

    • Channel是goroutine之间进行通信的一种方式,go所提倡的"应该以通信作为手段来共享内存"的最直接体现。

    Channel声明:
    ChannelType = ( "chan" | "chan" "<-" | "<-" "chan" ) ElementType .
    var ch chan int
    var ch1 chan<- int //ch1只能写
    var ch2 <-chan int //ch2只能读
    //make初始化
    putnamechan := make(chan string, 100) //带缓冲

    Goroutine

    关键字go,启用Goroutine的唯一途径

    //同时向五个人打招呼
    func main(){
       names := []string{"Eric","Tom","Jack","Jim"}
       for _,name:= range names{
           go func(){
               fmt.Printf("Hello,%s.
    ",name)
           }()
       }
       runtime.Gosched()
    }
    

    调度模型

    • Go的调度器内部有三个重要的结构:M,P,S

    • M:代表真正的内核OS线程,真正干活的人

    • G:代表一个goroutine,它有自己的栈,instruction pointer和其他信息(正在等待的channel等等),用于调度。

    • P:代表调度的上下文,可以把它看做一个局部的调度器,使go代码在一个线程上跑,它是实现从N:1到N:M映射的关键。

    图中看,有2个物理线程M,每一个M都拥有一个context(P),每一个也都有一个正在运行的goroutine。
    P的数量可以通过GOMAXPROCS()来设置,它其实也就代表了真正的并发度,即有多少个goroutine可以同时运行。
    图中灰色的那些goroutine并没有运行,而是出于ready的就绪态,正在等待被调度。P维护着这个队列(称之为runqueue),
    Go语言里,启动一个goroutine很容易:go function 就行,所以每有一个go语句被执行,runqueue队列就在其末尾加入一个
    goroutine,在下一个调度点,就从runqueue中取出一个goroutine执行。

    其他

    • defer语句:调用一个被 defer 的函数时在函数刚要返回之前延迟执行
    • panic/recover 异常处理语句

    缺陷

    • 编译生成的可执行文件尺寸非常大
    • 代码可读性差(x,y,z int, a []*struct)
    • go的滥用导致不可预见bug(注goroutine的使用应该是保守型的)

    有两种思维逻辑会想到使用goroutine

    • 业务逻辑需要并发

    比如一个服务器,接收请求,阻塞式的方法是一个请求处理完成后,才开始第二个请求的处理。其实在设计的时候我们一定不会这么做,我们会在一开始就已经想到使用并发来处理这个场景,每个请求启动一个goroutine为它服务,这样就达到了并行的效果。这种goroutine直接按照思维的逻辑来使用goroutine

    • 性能优化需要并发

    一个场景是这样:需要给一批用户发送消息,正常逻辑会使用

    for _, user := range users {
        sendMessage(user)
    
    }
    //但是在考虑到性能问题的时候,我们就不会这样做,如果users的个数很大,比如有1000万个用户?我们就没必要将1000万个用户放在一个routine中运行处理,考虑将1000万用户分成1000份,    //每份开一个goroutine,一个goroutine分发1万个用户,这样在效率上会提升很多。这种是性能优化上对goroutine的需求
    

    实例httpmq

    http协议实现的消息队列,数据持久化levelDb

    //httpmq    
    mux := http.NewServeMux()
    mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
    }  //net/http包起路由做拦截处理(put,get,status,view)
    //接收namedata参数
    
    //起四个channel
    putnamechan := make(chan string, 100) //入队name管道
    putposchan := make(chan string, 100)  //入队数据索引管道
    getnamechan := make(chan string, 100) //出队name管道
    getposchan := make(chan string, 100)  //出队数据索引管道
    
    //两个Goroutine做消息管道流入队出队操作
    go func(chan string, chan string) {
        for {
            name := <-putnamechan  //
            putpos := httpmq_now_putpos(name)
            putposchan <- putpos
        }
    }(putnamechan, putposchan)
    
    go func(chan string, chan string) {
        for {
            name := <-getnamechan
            getpos := httpmq_now_getpos(name)
            getposchan <- getpos
        }
    }(getnamechan, getposchan)
    
    //put入队操作
    putnamechan <- name
    putpos := <-putposchan
    
    queue_name := name + putpos
    if data != "" {
       db.Put([]byte(queue_name), []byte(data), nil)         
    } else if len(buf) > 0 {
       db.Put([]byte(queue_name), buf, nil)
    }
    
    //get出队操作
    getnamechan <- name
    getpos := <-getposchan
    
    if getpos == "0" {
       w.Write([]byte("HTTPMQ_GET_END"))
    } else {
       queue_name := name + getpos
       v, err := db.Get([]byte(queue_name), nil)
       if err == nil {
            w.Header().Set("Pos", getpos)
            w.Write(v)
        } else {
            w.Write([]byte("HTTPMQ_GET_ERROR"))
        }
    }
    

    put操作

    name --> putnameChannel --> 生成putPos --> putposChannel --> name+pos生成key持久化data

    get操作

    name --> getnameChannel --> 生成getPos --> getposChannel --> name+pos生成key getData

  • 相关阅读:
    linuxshell中"2>&1"含义
    Java中正数与负数操作>>、>>>的区别
    jsp el表达式
    struct2常用标签
    shell正则表达式
    IPV6学起来很费力?你看看,也就这样简单吧!
    STP、RSTP、MSTP合集思维导图
    HCIE之路--ISIS思维导图
    佛祖保佑,永不宕机! 永无BUG!
    震惊!ARP安全竟然还可以这样配置?
  • 原文地址:https://www.cnblogs.com/hexiweb/p/4958494.html
Copyright © 2011-2022 走看看