go基础语法学习笔记| 青训营笔记

86 阅读6分钟

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


title: go语言学习笔记 categories: -go


:=与=的区别

:=是声明并赋值,=就赋值

两种创建Map的方式

内置的make函数可以创建一个map:

ages := make(map[string]int) // mapping from strings to ints

我们也可以用map字面值的语法创建map,同时还可以指定一些最初的key/value:

ages := map[string]int{
    "alice":   31,
    "charlie": 34,
}

error obtaining VCS status: exit status 128

这个错误可以这么解决

go env -w GOFLAGS=-buildvcs=false

CURL命令是什么

Curl 是用于在本地计算机与远程服务器之间传输数据的命令行工具。 使用curl时您可以使用HTTP,HTTPS,SCP , SFTP和FTP等协议下载或上传数据。 Curl 提供了许多选项,使您可以恢复上传/下载,限制带宽,代理支持,用户身份验证等。

如何声明变量类型但不赋值

var ojo string
fmt.Println(ojo, "------------")

这个比较符合我对声明的理解

跑Go服务的时候遇到这个错误怎么处理panic: listen tcp 127.0.0.1:1080: bind: Only one usage of each socket address (p rotocol/network address/port) is normally permitted.

这个错误来源于端口号冲突,要么杀死占用180的端口,要么换一个端口

如何在win上使用nc

下载地址 eternallybored.org/misc/netcat…

将文件解压完以后win的安全中心可能会提示是个威胁,不用管,然后记得设好环境变量

一些示例代码方面的小问题

为什么下列代码中cutset中是\r\n

reader := bufio.NewReader(os.Stdin)
	input, err := reader.ReadString('\n')
	if err != nil {
		fmt.Println("An error occured while reading input. Please try again", err)
		return
	}

	input = strings.Trim(input, "\r\n")

因为go读入的时候就带着\r\n,让人头大,不知道是这个流输入的问题还是什么,和我以前的认知大相径庭

proxy中一些疑问的解答

auth以后执行connect为什么reader里还有东西

我个人理解是,reader是conn的一个缓冲流,也就意味着只要conn里还有东西,都会冲到reader里去

经过auth以后reader里还有东西吗?

这个我不太确定,我感觉是没有的,因为如果有的话实现起来感觉就乱套了,应该是分别管理两个区,一个区里的字符是主机写给程序的,另一个是程序写给主机的

_, err = conn.Write([]byte{socks5Ver, 0x00})

本地的主机得到这些以后通过conn又给了请求信息,所以后面这里reader里才又有了东西,最重要的就是理解那个socks5的一整个流程,在conn里本地主机还没给程序信息时,程序应该会暂时停在那里

connect的一整个流程是怎么样的

首先就是通过读取本地主机和程序的链接得到对应的目标主机信息,然后建立链接

dest, err := net.Dial("tcp", fmt.Sprintf("%v:%v", addr, port))

当建立成功以后向本地主机发送成功的信息,就下面这个

_, err = conn.Write([]byte{0x05, 0x00, 0x00, 0x01, 0, 0, 0, 0, 0, 0})

紧接着本地主机要和目标主机之间产生双向的信息流,这里不能是单向的就这种

-------》

《---------

因为单向容易堵塞,相当于信道就只有一个,两边都需要对方的信息来做出自己的反应,当都得等到对方接收到自己的信息才能得到对方的信息,通过这种并发的方式,就可以实现两边个发个的请求,不用等待对方接收自己信息的时间

go func() {
		_, _ = io.Copy(dest, reader)
		cancel()
	}()
	go func() {
		_, _ = io.Copy(conn, dest)
		cancel()
	}()

然后有个很神奇的点,我对于go实现并发的机制是这样看的,看似只有一个程序,实际上是两个程序,两个程序都能直接结束掉进程,但我们希望的是只有一方出现问题才进行切断,否则单纯的等待,所以有了下面的代码

ctx, cancel := context.WithCancel(context.Background())
	defer cancel()

	go func() {
		_, _ = io.Copy(dest, reader)
		cancel()
	}()
	go func() {
		_, _ = io.Copy(conn, dest)
		cancel()
	}()

	<-ctx.Done()

课后作业

  1. 字谜的修改

    func main() {
    	maxNum := 100
    	rand.Seed(time.Now().UnixNano())
    	secretNumber := rand.Intn(maxNum)
    	fmt.Println("The secret number is ", secretNumber)
    
    	fmt.Println("Please input your guess")
    	for {
    		var input string
    		_, err := fmt.Scanf("%s\n", &input)
    		if err != nil {
    			return
    		}
    		if err != nil {
    			fmt.Println("An error occured while reading input. Please try again", err)
    			continue
    		}
    
    		guess, err := strconv.Atoi(input)
    		if err != nil {
    			fmt.Println("Invalid input. Please enter an integer value")
    			continue
    		}
    		fmt.Println("You guess is", guess)
    		if guess > secretNumber {
    			fmt.Println("Your guess is bigger than the secret number. Please try again")
    		} else if guess < secretNumber {
    			fmt.Println("Your guess is smaller than the secret number. Please try again")
    		} else {
    			fmt.Println("Correct, you Legend!")
    			break
    		}
    	}
    }
    
    
  2. 课后作业2,3,基本的思路就是使用GroupWait,然后使个匿名函数进行并发,不要直接加go,因为这样子的话,一整个程序会卡死,我在自己的终端上跑了下,发现直接ctrl+z都退不出来,至于具体的原因,其实也很简单,死锁了,这里一定要注意,因为defer wq.Done()是程序运行结束以后才会执行,导致了wq的值一直减不下来

    package main
    
    import (
    	"bytes"
    	"encoding/json"
    	"fmt"
    	"io/ioutil"
    	"log"
    	"net/http"
    	"os"
    	"sync"
    )
    
    type DictRequest struct {
    	TransType string `json:"trans_type"`
    	Source    string `json:"source"`
    	UserID    string `json:"user_id"`
    }
    
    type Ans struct {
    	Result struct {
    		Msg  string `json:"msg"`
    		Code int    `json:"code"`
    	} `json:"result"`
    	Data struct {
    		Entries []struct {
    			Explain string `json:"explain"`
    			Entry   string `json:"entry"`
    		} `json:"entries"`
    		Query    string `json:"query"`
    		Language string `json:"language"`
    		Type     string `json:"type"`
    	} `json:"data"`
    }
    
    type DictResponse struct {
    	Rc   int `json:"rc"`
    	Wiki struct {
    		KnownInLaguages int `json:"known_in_laguages"`
    		Description     struct {
    			Source string      `json:"source"`
    			Target interface{} `json:"target"`
    		} `json:"description"`
    		ID   string `json:"id"`
    		Item struct {
    			Source string `json:"source"`
    			Target string `json:"target"`
    		} `json:"item"`
    		ImageURL  string `json:"image_url"`
    		IsSubject string `json:"is_subject"`
    		Sitelink  string `json:"sitelink"`
    	} `json:"wiki"`
    	Dictionary struct {
    		Prons struct {
    			EnUs string `json:"en-us"`
    			En   string `json:"en"`
    		} `json:"prons"`
    		Explanations []string      `json:"explanations"`
    		Synonym      []string      `json:"synonym"`
    		Antonym      []string      `json:"antonym"`
    		WqxExample   [][]string    `json:"wqx_example"`
    		Entry        string        `json:"entry"`
    		Type         string        `json:"type"`
    		Related      []interface{} `json:"related"`
    		Source       string        `json:"source"`
    	} `json:"dictionary"`
    }
    
    func query(word string) {
    	client := &http.Client{}
    	request := DictRequest{TransType: "en2zh", Source: word}
    	buf, err := json.Marshal(request)
    	if err != nil {
    		log.Fatal(err)
    	}
    	var data = bytes.NewReader(buf)
    	req, err := http.NewRequest("POST", "https://api.interpreter.caiyunai.com/v1/dict", data)
    	if err != nil {
    		log.Fatal(err)
    	}
    	req.Header.Set("Connection", "keep-alive")
    	req.Header.Set("DNT", "1")
    	req.Header.Set("os-version", "")
    	req.Header.Set("sec-ch-ua-mobile", "?0")
    	req.Header.Set("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.51 Safari/537.36")
    	req.Header.Set("app-name", "xy")
    	req.Header.Set("Content-Type", "application/json;charset=UTF-8")
    	req.Header.Set("Accept", "application/json, text/plain, */*")
    	req.Header.Set("device-id", "")
    	req.Header.Set("os-type", "web")
    	req.Header.Set("X-Authorization", "token:qgemv4jr1y38jyq6vhvi")
    	req.Header.Set("Origin", "https://fanyi.caiyunapp.com")
    	req.Header.Set("Sec-Fetch-Site", "cross-site")
    	req.Header.Set("Sec-Fetch-Mode", "cors")
    	req.Header.Set("Sec-Fetch-Dest", "empty")
    	req.Header.Set("Referer", "https://fanyi.caiyunapp.com/")
    	req.Header.Set("Accept-Language", "zh-CN,zh;q=0.9")
    	req.Header.Set("Cookie", "_ym_uid=16456948721020430059; _ym_d=1645694872")
    	resp, err := client.Do(req)
    	if err != nil {
    		log.Fatal(err)
    	}
    	defer resp.Body.Close()
    	bodyText, err := ioutil.ReadAll(resp.Body)
    	//fmt.Println(bodyText)
    	if err != nil {
    		log.Fatal(err)
    	}
    	if resp.StatusCode != 200 {
    		log.Fatal("bad StatusCode:", resp.StatusCode, "body", string(bodyText))
    	}
    	var dictResponse DictResponse
    	err = json.Unmarshal(bodyText, &dictResponse)
    	if err != nil {
    		log.Fatal(err)
    	}
    	fmt.Println(word, "UK:", dictResponse.Dictionary.Prons.En, "US:", dictResponse.Dictionary.Prons.EnUs)
    	for _, item := range dictResponse.Dictionary.Explanations {
    		fmt.Println(item)
    	}
    }
    
    func query1(word string) {
    	client := &http.Client{}
    	url := "https://dict.youdao.com/suggest?num=5&ver=3.0&doctype=json&cache=false&le=en&q=" + word
    	req, err := http.NewRequest("GET", url, nil)
    	if err != nil {
    		log.Fatal(err)
    	}
    	req.Header.Set("Accept", "application/json, text/plain, */*")
    	req.Header.Set("Accept-Language", "zh-CN,zh;q=0.9")
    	req.Header.Set("Connection", "keep-alive")
    	req.Header.Set("Cookie", "OUTFOX_SEARCH_USER_ID_NCOO=1409548759.9198873; OUTFOX_SEARCH_USER_ID=-175778370@120.36.21.15")
    	req.Header.Set("Origin", "https://www.youdao.com")
    	req.Header.Set("Referer", "https://www.youdao.com/")
    	req.Header.Set("Sec-Fetch-Dest", "empty")
    	req.Header.Set("Sec-Fetch-Mode", "cors")
    	req.Header.Set("Sec-Fetch-Site", "same-site")
    	req.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/106.0.0.0 Safari/537.36")
    	req.Header.Set("sec-ch-ua", `"Chromium";v="106", "Google Chrome";v="106", "Not;A=Brand";v="99"`)
    	req.Header.Set("sec-ch-ua-mobile", "?0")
    	req.Header.Set("sec-ch-ua-platform", `"Windows"`)
    	resp, err := client.Do(req)
    	if err != nil {
    		log.Fatal(err)
    	}
    	defer resp.Body.Close()
    	bodyText, err := ioutil.ReadAll(resp.Body)
    	if err != nil {
    		log.Fatal(err)
    	}
    	//fmt.Printf("%s\n", bodyText)
    
    	var ans Ans
    
    	json.Unmarshal(bodyText, &ans)
    	//fmt.Println(ans)
    
    	for _, explain := range ans.Data.Entries {
    		fmt.Println(explain.Entry, explain.Explain)
    	}
    
    }
    
    func main() {
    	if len(os.Args) != 2 {
    		fmt.Fprintf(os.Stderr, `usage: simpleDict WORD
    	example: simpleDict hello
    			`)
    		os.Exit(1)
    	}
    	fmt.Println(os.Args)
    
    	word := os.Args[1]
    
    	var wq sync.WaitGroup
    	wq.Add(1)
    
    	go func(word string) {
    		defer wq.Done()
    		query1(word)
    	}(word)
    
    	go func(word string) {
    		defer wq.Done()
    		query(word)
    	}(word)
    
    	wq.Wait()
    	//fmt.Println("--------")
    }