Go语言上手-基础语言|青训营笔记

119 阅读6分钟

这是我参与「第三届青训营-后端场」笔记创作活动的第一篇笔记。

源码

课程源码:github.com/wangkechun/…

短链接:hi-hi.cn/go

Go语言特点

  1. 高性能、高并发
  2. 语法简单,学习曲线平缓
  3. 丰富的标准库
  4. 完善的工具链
  5. 静态链接
  6. 快速编译
  7. 跨平台
  8. 垃圾回收

开发环境

  1. 集成开发环境

(略)

  1. 基于云的开发环境

gitpod.io/#github.com…

短链接:hi-hi.cn/gitpod

基础语法

Hello World

package main



import(

    "fmt"

)

func main(){

    fmt.PrintIn("Hello World") 

}

变量

// 声明变量

var a = "initial"

var b, c int = 1, 2 

f := float32(e)     

常量

// 声明常量

const s string = "constant"

常量可根据上下文自动确定类型

循环

条件无括号

for j := =7; j < 9; j++{    // 三个部分均可省略,若均为空则为死循环

    fmt.PrintIn(j)

}

switch-case分支

变量名无括号

无break也不需跑完所有case分支

可使用任意变量类型

switch后不加变量,在case后加条件可取代if-else

数组

具有编号且长度固定

// 声明数组

var a [5]int

切片

可变长度

 s:= make([]string, 3)

 s = append(s, "d") // 需重新赋值回原数组

 c := make([]strinh,len(s)) // 创建时即可指定长度

 copy(c, s)  // 在两个数组间复制

 s[2:5]   // 不支持负数索引

map (哈希/字典)

m := make(map[string]int)

 m["one"] = 1

 r, ok := m["unknow"]  // 确认key是否存在于map中

 delete(m, "one") // 从mao中删除

 // map完全无序

range

for i, num := range nums{    // 返回索引和数值,不需要返回索引可用下划线free

    ...                          // 遍历map时返回key和value

}

函数

// 示例:两数相加

func add(a int, b int) int{

    return a + b

}
func exists(m map[string]string, k string)(v string, ok bool){     // 返回多个值

    v, ok = m[k]                       // 第一个为实际值,第二个为错误信息

 return v,ok

}

指针

主要用于对常用参数进行修改

// 不起作用,因为其中的n为拷贝

func add2(n int){

    n += 2

}
// 要使用指针,在参数前加*,使用时需在参数前加&

func add2ptr(n *int){

    *n += 2

}

...

add2ptr(&n)

结构体

type user struct{

    name          string

    password      string

}

 a:= user{name:"wang", password:"1024"}

 

 // 读取写入

 d.name = "wang"

 

 // 结构体可作为参数,使用指针可对结构体进行修改,也可以防止对大型结构体拷贝的开销

func checkPassword(u user, password string)bool{

    return u.password == password

}

结构体方法

func(u user)checkPassword(password string)bool{

    return u.password == password

} 



// 结构变为结构体方法后可用a来调用该函数

a := user(name: "wang", password: "1024")

a.checkPassword("2048")

错误处理

func findUser(users []user, name string)(v *user, err error){

    for _, u := range users{

        if u.name == name{

            return &u, nil

            }

            return nil, errors.New("not found")

}



func main(){

    u, err := findUser([]user{{"wang", "1024"}}, "wang"if err != nil{

        fmt.PrintIn(err)

        return

     }

     fmt.PrintIn(u.name)// wang 

     if u, err := findUser([]user{{"wang", "1024"}}, "li"); err != nil{

         fmt.PringIn(err)//not found

         return

     }else{

          fmt.PrintIn(u.name)

     }

 }

字符串操作

a := "hello"

// 以下省略fmt.PrintIn(string. )

Contains(a, "ll")                    //true

Count(a,"l")                         //2

HasPrefix(a, "he")                   //true

HasSuffux(a, "llo")                  //true

Index(a, "ll")                       //2 查找某个字符串的位置

Join([]string{"he", "llo"}, "-")     //he-llo

Repeat(a, 2)                         //hellohello 

Replace(a, "e", "E", -1)             //hEllo

Spit("a-b-c", "-")                   //[a b c]

ToLower(a)                           //hello

ToUpper(a)                           //HELLO

len(a)                               //5



b := "你好"

len(b)    //6     

字符串格式化

s := "hello"

n := 123

p := point{1, 2}

fmt.PrintIn(s, n)  //hello 123

fmt.PrintIn(p)     //{1 2}



//Go中用%v即可输出全类型数据

fmt.Printf("s=%v\n", s)  //s=hello

fmt.Printf("n=%v\n", n)  //n=123

fmt.Printf("p=%v\n", p)  //p={1 2}

fmt.Printf("p=%+v\n", p) //p={x:1 y:2}

fmt.Printf("p=%#v\n", p) //p=main.point{x:1 y:2}



f := 3.141592653

fmt.PrintIn(f)          //3.141592653  

fmt.Printf("%.2f\n", f) //3.14

JSON处理

// 字符段名称需首字母大写

package main

import{

    "encoding/json"

    "fmt"

}



type userInfo struct{

    Name  string

    Age   int  'json:"age"' //在输出时将显示age

    Hobby []string

}



func main(){

    a := userInfo(Name: "wang", Age: 18, Hobby:[]string{"Golang", "TypeScript"}

    buf, err := json.Marshal(a)

    if err != nil{

        panic(err)

    }

    fmt.PrintIn((buf))       //{123 34 78 97...}

    fmt.PrintIn(string(buf)) //{Name:"wang",age:18,Hobby:{"Golang","TybeScript"}

    

    var b userInfo

    err = json.Unmarshal(buf, &b)

    if err != nil{

        panic(err)

    }

    fmt.Printf("%#n\n", b) //main.userInfo{Name:...}

时间处理

now := time.Now()

fmt.PrintIn(now)

t := time.Date(2022, 3, 27, 1, 25, 36, 0, time.UTC)

t2 := time.Date(2022, 3, 27, 2, 30, 36, 0, time.UTC)

fmt.PrintIn(t))                                                //2022-03-27 01:25:36 +0000 UTC

fmt.OrintIn(t.Year(),t.Month(), t.Day(), t.Hour(), t.Minute())//2022 March 21 1 25

fmt.PrintIn(t.Format("2006-01-02 15:04:05")                     //202-03-27 01:25:36



diff := t2.Sub(t)

fmt.PrintIn(diff)                          //1h5m0s

fmt.PrintIn(diff.Minutes(), diff.Seconds())//65 3900

t3, err := time.Parse("2006-01-02 15:04:05", "2022-03-27 01:25:36")

if err != nil{

    panic(err)

}

fmt.PrintIn(t3 == t)     //true

fmt.PrintIn(now, Unix()) //1648738080  //时间戳

数字解析

import {

    "fmt"

    "strconv"

}



func main(){

    f, _ := strconv.ParseFloat("1.234", 64)

    fmt.PrintIn(f) //1.234

    

    n, _ := strconv.ParseInt("111", 10, 64)

    fmt.PrintIn(n) //111

    

    n, _ := strconv.ParseInt("0x1000", 0, 64)

    fmt.PrintIn(n) //4096

    

    n2, _ := strconv.Atoi("123") //Atoi:十进制字符串转为数字 itoA:数字转为字符串

    fmt.PrintIn(n2) //123

    

    n2, err := strconv.Atoi("AAA")

    fmt.PrintIn(n2, err) //0 strconv.Atoi: parsing"AAA" invalid syntax

进程信息

import{

    "fmt"

    "os

    os/exec"

}



func main(){

//go run example/20-env/main.go a b c d

    fmt.PrintIn(os.Args)               //[/var/folders/8p/n34xxfnx38dg8bv_x8162t_m0000gn/T/go-build3406981276/b001/exe/main a b c d]

    fmt.PrintIn(os.Getenv("PATH"))     // /user/local/go/bin...

    fmt.PrintIn(os.Setenv("AA", "BB"))



    buf, err := exec.Command("grep", "127.0.0.1", "/etc/hosts").CombinedOutput()

    if err != nil{

        panic(err)

    }

    fmt.PrintIn(string(buf)) // 127.0.0.1     localhost

}

实战

猜谜游戏

  1. 生成随机数
package main



import(

    "fmt"

    "math/rand"

)

func main(){

    maxNum := 100

    secretNumber := rand.Intn(maxNumber)

    fmt.PrintIn("The secret number is ", secretNumber)

问题:多次输出结果为相同数字

// 未添加随机数种子

解决:头文件加“time”,用时间戳初始化随机数种子

rand.Seed(time.Now().UnixNano())

  1. 读取用户输入
fmt.PrintIn("Please input your guess")

readr := bufo.NewReader(os.Stdin)

input, err := reader.ReadString('\n') //读取一行输入

if err != nil{

    fmt.PrintIn("An error occired while reading input.Please try again", err)

    return

}

input = strings.TrimSuffix(input, "\n")//去掉换行符,win系统为\r\n



guess, err := strconv.Atoi(input)//将字符串转化为数字

if err != nil{

    fmt.PrintIn("Invalid input.Please enter an integer value")

    return

}

fmt.PrintIn("Your guess is", guess)
  1. 实现判断逻辑
  2. 实现游戏循环

加入for循环,将return改为continue,只有胜利时为break

在线词典

  1. 抓包

以彩云小译为例

fanyi.caiyunapp.com/

Network-dict-POST

  1. 代码生成

curlconverter.com/#go

  1. 生成request body
  2. 解析response body

oktools.net/json2go

  1. 打印结果

SOCKS5代理

  1. 原理
  • 握手阶段 浏览器向socks5发送请求
  • 认证阶段 socks返回认证方式,00表示不需要认证
  • 请求阶段 认证通过后浏览器向socks5发起请求,一般为connection请求,代理服务器收到响应后会和后端服务器建立连接,然后返回一个响应
  • relay阶段 浏览器发送正常请求,代理服务器收到后将请求转到真正的服务器上,真正的服务器若返回响应,也会把响应转发到浏览器
  1. TCP echo server
  2. auth
  3. 请求阶段
  4. relay阶段

//代理部分看懂课程源码了,但还不太能用文字清晰地表达出来,之后有时间可以单独整理