go语言基础与项目实践|青训营笔记

98 阅读4分钟

go语言基础与项目实践|青训营笔记

这是我参与「第五届青训营」笔记创作活动的第一天

特点

  • 垃圾回收机制: 类似java,可以忽略程序执行过程中内存空间的管理
  • 强类型语言:如整数,浮点,字符串,布尔等

基础语法

  • package
    • 首行确定入口文件
    • 单文件的代码必须用package main,否则会出现报错
    • eg: package main,但是如果不是作为主函数执行,可以用其他的
  • import 导入包
    • 格式:import{包1,包2,包3....}
    • fmt:输入输出相关库
    • encoding/json :json相关操作的文件 如:json.Marshal()函数
    • encoding/xml -等等
  • 主函数
    • func main(){程序执行内容}
  • 变量
    • 强类型语言
    • 常见类型:整数,浮点,布尔,字符串,变量特征基本和C++和java类似
    • 变量声明(主要区别)
      • var 变量名=值 eg:var a=1;
      • var 变量名 变量类型 = 值 eg: var a int =3; var a string="123"
      • var 变量名:=变量类型 值 eg: f:=int 12
  • 常见的语句类型(只记录常见类型)
    • 分支语句
      • if 语句 -格式 if 条件 { 执行1 执行2 }
        • 注意
          • 条件不用加括号
          • ‘{’ 必须和条件在同一行,不可以换行
      • switch 语句
          switch a{
           case 条件1: 执行1 //不用再加break
           case 条件2: 执行2
           case 条件3:执行3
           default: 条件4
          }
        
        • 注意
          • 条件不用加括号
          • ‘{’ 必须和条件在同一行,不可以换行
          • 与C的不同,执行语句后不用加break打断,即若同时满足1只执行1;
    • 循环语句(go中只有for循环)
      • for循环
        • 常见语句
        for {//for后不加条件,类似与死循环
          循环体
         }
         //类似C的for循环,注意:条件不加括号,“{”的位置。
         for i:=1;i<9;i++{
           循环体
          }
        
  • 常见数据结构
    • 数组(array)
      • 数组的定义: eg:var a[5]int
      • 其余和C中数组类似,长度固定不常用。
    • 切片(slice)
      • 类似变长数组(可扩容)
      • 切片定义:
      s:=make([]string,5)//初始容量为3的字符切片
      var s= make([] int, 4)//初始容量为4的切片
      
      • 切片的赋值和相关操作类似数组
      • 特殊
      s=append(s,值) append必须赋值回给s
      c:=make([]string,2)
      copy(c,s)  //将s中的内容复制到C,到那时由于len(c)<len(s)所以,值赋值s的前两个元素
      s[2:5]取s index=2的元素到index=5的元素(不包含第五个)的部分
      
    • Map hash/字典
      • 类似字典和hash表的键值对
      • 定义
      s:=make(map[string(键的类型)]int(值的类型))
      var s= make(map[string(键的类型)]
      
      • 操作类似python字典
      //m是一个初始为空的字典
      //添加key1-value1,key2-value2的键值对
      m['key1']=value1
      m['key2']=value2 
      delete(m,key1)删除m中key1-value1的键值对
      //map是完全乱序的
      thevalue,ok=m['one']//获取key=one的值,若存在这样的键值对,ok=nil,thevalue=value,若不存在这样的键值对则 ok!=nil而是等于err等
      
  • 遍历( range)
    • range遍历数组
      //nums[13,14]
      for i,num :=range nums{ 
           fmt.println("index",i,"value",num)
           //结果是 index 0 value 13
           //      index 1 value 14
       i:index;
       num:值
       }
       //如果只想取num的值可以用 '_'替代i,即可不取返回的index
      
    • range遍历map
          e := make(map[string]int)
          e["one"] = 1
          e["two"] = 2
          for key, _ := range e { //只取key值
             fmt.Println("key", key)
          }
          //取key,value的值
          for key,value := range e{
          fmt.Println("key", key,"value",value)
          }
      
  • 函数
    • 定义 func 函数名(参数){函数体}
      func 函数名(类型 parm1,类型 parm2)
      {
          函数体
          }
      
  • 指针
    • 基本与C指针相同,&取地址,*取指针指向的值
  • 结构体
    • 定义与C类似,但是变量名在前,类型在后
     type 结构体类型名 struct{
     变量名 类型
     变量名 类型
     ....
     }
     eg:
     type student struct{
     id int
     name string
     }
    
    • 声明结构体变量 eg: stu1:=student{id:1,name:"Tom"}//若未全部指定,未指定的值取空值
    • 结构体方法(类似类成员函数)
    定义
    func (形参 结构体名) 函数名(参数列表)(返回类型,可以有多个返回值)不填默认为空{函数体}
    eg:
    func (s *student) setinfo(int id, int name)
    {
        s.id=id
        s.name=name
    }
    //调用
    var stu2 student
    stu.setinfo(2,"jack")
    
  • 错误处理
    • go函数中可以有多个返回值,需要用多个变量接受,可以专门返回err eg

image.png

  • 字符串函数//可以直接网上文档,这里不赘述
  • 格式化输出(不用区分%s,%d,可以全部用%v)
    fmt.printf("stu=%v",stu)//打印值s={1,Tom}
    fmt.printf("stu=%+v",stu)//打印值s={id:1 name:Tom}
    fmt.printf("stu=%#v",stu)//打印键-值s=main.student{id:1, name:"Tom"} //确定包的位置
    
  • JSON转化
  • json.Marshal(类型)//序列化
  • json.Unmarshal(类型,&变量名)//反序列化 -注意
  序列化后字段名首字母默认大写
  特别是序列化结构体时,结构体成员变量需要时首字母大写才能序列号
  如果需要字段名小写,可以在结构体成员变量后用``进行标注
  eg:
      type student struct {
         id   int //首字母未大写,序列化未空
         name string
      }
      type student struct {
         Id   int //字母大写,序列化成功
         Name string `json:name` //序列化后字段为name
      }
  • 时间管理
    • 使用前导入time 包
    • time.now() //获取当前时间
    • time.Date(年,月,日,时,分,秒,0,时区)
    • 声明变量 t:=time.Date(.....)后 可以用 t.year()等获取相关值
    • time.Unix() 时间戳
  • 字符串转数字
    • strconv 包
    • strconv.PareseInt(str,机制,64【返回64位精度】)
    • strconv.Atoi(str) //eg: "1111"->1111
  • 进程管理
    • os.args 获取命令行参数
    • os.Getenv("环境变量名")//获取环境变量
    • os.setenv('环境变量名',值)//设定环境变量
    • os.exec(str)执行命令行文件

项目实战

实战项目一--猜词游戏

  本项目中我主要学习到的是go的用户输入的实现方法,总结如下

  • 输入
    • 流读取
      reader := bufio.NewReader(os.Stdin) //从标准输入流中获取buf
      input, err := reader.ReadString('\n')//从输入流中以'/n'作为结束读取字符串
      if err != nil {
         fmt.Println("error when input")
         continue
      }
      input = strings.TrimSuffix(input, "\r\n")//删除字符串末尾的"\r\n"
      
    • scanf方法读取(类似C和c++)【作业中要求使用】
    scanf("%s",&变量)//注意此处不可以用%v替代所有类型
    
    • ps rand 函数的使用类似C和JAVA,一般都用时间戳作为seed

实战项目二---在线词典

  本项目主要是介绍了工具网站和代码生成网站在实际项目中的使用,和json数据的处理

  • 工具网站
    • 代码生成 curlconverter.com
    • json的格式化处理 oktools.iokde.com/
    • ps:注意:
      • 代码生成时注意
        • windows中的curl命令生成go代码时,payload中 "key":"value"/key:"value",可能被解析为key:value,不确定是否是我的浏览器问题,但是还是写出来警醒以下。
      • json的格式化处理
        • 该网站只能实现一重json转格式化,可能出现转化不完全的情况,可以手动将未完全转化的部分单独转化一次 例如:火山翻译中details.details是一个结构体序列化但是嵌套后直接转化为string
  • json 数据处理
    • json.marshal(结构体)
      • 返回二进制数组,和错误信息,若要打印字符串需用string转化
    • json.unmarshal(需要进行序列化的二进制流,&存储用变量)
      • 只返回error信息
      • 反序列化结果即为存储用变量的结构体类型变量
  • http请求
    • http.client{设置参数,可为空}//用于构造一个客户端
      • 使用时将地址赋给变量 egclient=&http.client{}
    • http.NewRequest("请求方式",url,data)
      • 注意:data是二进制形式,在构造时需用 bytes.NewReader生成
      • 返回一个request请求变量和error信息
    • client.do(req) 发送请求
      • 返回相应信息与error信息

实战项目3--socks5代理

  本项目主要知识点时net包的使用和简单多线程的实现

  • net包的使用
    • net.listen(“协议类型/tcp/udp...”,地址:端口)
      • 返回一个server类型+error
    • server.accept()//返回一个连接对象(connection)//也是一个二进制流,存储用户发来的信息
      • 利用bufio.NewReader(conn)获取发来的流
      • 利用 coon.Write(byte[]) 向目标发送信息
    • 其中网络协议协议相关内容此处不做叙述
  • 简单的并发
    • goroutine 主协程下可以有多个线程,并行的基础
    go func1() 
    go func2()
    return;
    
    • func1(),与func2()会与主携程并行运行,由于是并行操作所以很可能在func1,func2未运行完时,主协程结束,使func1,2也结束
    • 解决方案
      • 利用 sync.WaitGroup包,一个进程时启动一个 wg.add(1),一个进程完成后wg.Down() wg总数-1,同时主进程中加入wg.wait()即可等待所有进程执行完毕后再继续
      • 利用 context库
      ctx,err:=context.WithCancel(context.Background())
      defr cancel()
      go func(){
      func1()
      cancel()
      }()//调用该函数
      go func(){
      func2()
      cancel()
      }
      <-ctx.Down()
      实现func1,func2任意一个完成即继续执行
      
      

以上就是本次课程一个简单总结

标题:走进 Go 语言基础语言 - 掘金

网址:juejin.cn/course/byte…