Powered by:NEFU AB-IN
文章目录
- Go 语言的实战案例 | 青训营
- Go补充简介
- 猜数游戏
- 在线词典项目
Go 语言的实战案例 | 青训营
- GO语言工程实践课后作业:实现思路、代码以及路径记录
Go补充简介
在计算机编程领域,Go 语言(也称为 Golang)正逐渐成为越来越受欢迎的选择。它是一门由 Google 开发的开源编程语言,以其简洁性、高效性和强大的并发支持而闻名。Go 语言的设计目标是提供一种简单易学、高效可靠的编程语言,同时具备 面向对象和函数式编程的特性。
Go 语言的实战案例是一个很好的方式来了解和掌握这门语言的基础知识。通过实际的应用场景和案例,我们可以更深入地了解 Go 语言的特点、语法和最佳实践。下面我将分享一些关于走进 Go 语言基础语言的实战案例的笔记。
并发编程: Go 语言在并发编程方面有着独特的优势。通过 Goroutine 和 Channel 的概念,Go 语言使并发编程变得简单且高效。实战案例中,我们可以通过编写并发的网络爬虫、并发处理大量数据等任务来体验 Goroutine 和 Channel 的强大威力。
Web开发: Go 语言具备强大的网络编程能力,因此在 Web 开发领域也有着广泛的应用。通过实战案例,我们可以学习如何使用 Go 语言构建高性能的 Web 服务器、RESTful API,以及处理请求和响应等常见任务。
数据库操作: Go 语言提供了丰富的数据库操作库,如标准库中的 database/sql 包以及第三方的 ORM 框架。实战案例中,我们可以学习如何使用 Go 语言与各种数据库进行交互,执行查询、插入和更新等操作,并学习如何优化数据库操作的性能。
文件处理和系统编程: Go 语言对于文件处理和系统编程也有着良好的支持。实战案例可以涵盖文件的读写、目录的遍历、系统命令的执行等方面。这些案例将帮助我们理解 Go 语言在操作系统级别编程时的优势和技巧。
测试和性能优化: Go 语言注重代码质量和性能,因此在实战案例中,测试和性能优化也是不可或缺的内容。我们可以学习如何编写单元测试和集成测试,并使用性能分析工具来发现和改进代码中的性能瓶颈。
平台和工具开发: Go 语言本身就是一个非常强大的工具和平台开发语言。实战案例可以涵盖开发各种工具、命令行应用、服务器软件等。我们可以学习如何使用 Go 语言构建高效的命令行工具、自定义 HTTP 服务器、消息队列等应用。
跨平台开发: Go 语言支持跨平台编译,这使得我们可以轻松地在不同操作系统上构建和部署应用程序。通过实战案例,我们可以学习如何使用 Go 语言开发跨平台应用,为不同操作系统编译和交付可执行文件。
微服务和分布式系统: 微服务和分布式系统是现代软件开发中的热门话题。Go 语言在构建微服务和分布式系统方面具有优势,因为它提供了轻量级的协程和高效的网络库。实战案例可以涵盖服务间通信、负载均衡、服务发现等方面,帮助我们理解和应用微服务架构和分布式系统的概念。
通过以上的实战案例,我们可以全面掌握 Go 语言的基础语言特性,并了解如何在实际项目中应用它们。同时,实战案例也能帮助我们熟悉和理解 Go 语言的开发流程、工具链以及最佳实践。
总结起来,走进 Go 语言基础语言的实战案例是学习和掌握这门语言的重要途径之一。通过实际的应用场景和案例,我们可以深入理解 Go 语言的特点和优势,掌握其核心语法和常用库的使用。
猜数游戏
由于逻辑过于简单,在此不再赘述
知识点
-
包管理和导入:在 Go 语言中使用
import
来导入所需的包,比如fmt
、math/rand
、os
等。 -
随机数生成:使用
math/rand
包的rand.Seed()
和rand.Intn()
函数来生成随机整数。 -
时间处理:使用
time
包获取当前时间的纳秒级表示,用于初始化随机数生成器的种子值。 -
用户输入输出:使用
bufio
包的bufio.NewReader()
和ReadString()
函数来读取用户输入(即读取一行),并使用fmt
包的Println()
函数来打印输出。 -
字符串处理:使用
strings
包的Trim()
函数来处理输入中的结尾换行符。 -
类型转换:使用
strconv
包的Atoi()
函数将字符串转换成整数。 -
循环:使用
for { ... }
来创建一个无限循环,使得游戏可以持续进行,直到玩家猜对为止。 -
条件语句:使用
if
和else if
来根据玩家猜测和秘密数字的比较结果给出相应的提示。
package main
import (
"bufio"
"fmt"
"math/rand"
"os"
"time"
)
var (
in = bufio.NewReader(os.Stdin)
out = bufio.NewWriter(os.Stdout)
)
func Read[T any]() T {
var i T
fmt.Fscan(in, &i)
return i
}
func main() {
defer out.Flush()
maxNum := 100
rand.Seed(time.Now().UnixNano())
secretNumber := rand.Intn(maxNum)
// fmt.Println("The secret number is ", secretNumber)
fmt.Println("Please input your guess")
// reader := bufio.NewReader(os.Stdin)
for {
// input, err := reader.ReadString('\n')
// if err != nil {
// fmt.Println("An error occured while reading input. Please try again", err)
// continue
// }
// input = strings.Trim(input, "\r\n")
// guess, err := strconv.Atoi(input)
guess := Read[int]()
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
}
}
}
结果截图
在线词典项目
-
fanyi.caiyunapp.com/
-
点击payload和preview
Payload是数据包中实际传输的数据内容,而Preview是对Payload的一个预览或摘要,用于快速了解数据包的内容。Payload是数据的实体,而Preview则是展示给用户的一个概括或摘要。
-
采用wireshark也可实现抓包
-
请求复制 (目的是为了用go来模拟发送相同的请求)
-
将请求复制为cURL(bash)是指将一个HTTP请求的参数、请求头和URL等信息,以curl命令的形式拷贝到终端中。
-
复制生成的代码就是拷贝得到的curl命令,它可以在命令行中直接执行,发送与拷贝的请求相同的HTTP请求。
-
在给定的示例中,这段代码表示一个发送到 https://api.interpreter.caiyunai.com/v1/dict 的HTTP POST请求。请求头包含多个参数,如authority、accept、accept-language等。请求体中的JSON数据为"trans_type":“en2zh"和"source”:“good”。
-
使用复制生成的代码,你可以在终端中直接执行该命令,从而发送相同的HTTP请求,并获取该请求的响应结果。
-
Curl是一个用于发送和接收HTTP请求的命令行工具。它支持多种协议,包括HTTP、HTTPS、FTP、SMTP等,并提供了许多可配置的选项和参数,使用户可以根据需要定制和控制HTTP请求的各个方面。Curl可以通过命令行界面直接执行,也可以与脚本语言(如bash、Python等)一起使用,从而方便地集成到各种开发和测试场景中。Curl常用于测试和调试Web应用程序,以及进行API接口的测试和集成。
curl 'https://api.interpreter.caiyunai.com/v1/dict' \ -H 'authority: api.interpreter.caiyunai.com' \ -H 'accept: application/json, text/plain, */*' \ -H 'accept-language: zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6' \ -H 'app-name: xy' \ -H 'content-type: application/json;charset=UTF-8' \ -H 'device-id: 313abb19c54ae93fa733afae2f9fca47' \ -H 'origin: https://fanyi.caiyunapp.com' \ -H 'os-type: web' \ -H 'os-version;' \ -H 'referer: https://fanyi.caiyunapp.com/' \ -H 'sec-ch-ua: "Not/A)Brand";v="99", "Microsoft Edge";v="115", "Chromium";v="115"' \ -H 'sec-ch-ua-mobile: ?0' \ -H 'sec-ch-ua-platform: "Windows"' \ -H 'sec-fetch-dest: empty' \ -H 'sec-fetch-mode: cors' \ -H 'sec-fetch-site: cross-site' \ -H 'user-agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/115.0.0.0 Safari/537.36 Edg/115.0.1901.203' \ -H 'x-authorization: token:qgemv4jr1y38jyq6vhvi' \ --data-raw '{"trans_type":"en2zh","source":"good"}' \ --compressed
-
-
代码生成器 Convert curl to Go (curlconverter.com)
将curl请求生成go代码
strings.NewReader是一个函数,它返回一个实现io.Reader接口的类型strings.Reader。strings.Reader可以用来读取一个字符串的内容。
io.Reader是一个接口,它定义了一个用于读取数据的方法Read。任何实现了Read方法的类型都可以被称为io.Reader。这个接口常用于读取输入流的数据,如文件、网络连接、字节数组等。通过实现io.Reader接口,可以方便地进行读取操作,比如逐行读取文件内容或按照指定大小读取数据块。
-
补充说明
接收一个 io.Reader 类型的参数,可以传入 os.Stdin,因为 os.Stdin 实现了 io.Reader 接口。
在Go语言中,io.Reader 是一个接口,它定义了一个读取数据的方法 Read。任何实现了 Read 方法的类型都可以被视为 io.Reader 类型。
os.Stdin 是一个 os.File 类型的值,而 os.File 类型实现了 Read 方法,因此它也被视为实现了 io.Reader 接口。
/* * @Author: NEFU AB-IN * @Date: 2023-08-23 10:35:07 * @FilePath: \GoTest\5\5.go * @LastEditTime: 2023-08-23 11:52:24 */ package main import ( "fmt" "io" "log" "net/http" "strings" ) func main() { client := &http.Client{} // 创建http client var data = strings.NewReader(`{"trans_type":"en2zh","source":"good"}`) // NewReader创建一个从s读取数据的Reader(流) req, err := http.NewRequest("POST", "https://api.interpreter.caiyunai.com/v1/dict", data) // 创建请求,data为流(减少发送的内存,流式创建请求) if err != nil { log.Fatal(err) } req.Header.Set("authority", "api.interpreter.caiyunai.com") req.Header.Set("accept", "application/json, text/plain, */*") req.Header.Set("accept-language", "zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6") req.Header.Set("app-name", "xy") req.Header.Set("content-type", "application/json;charset=UTF-8") req.Header.Set("device-id", "313abb19c54ae93fa733afae2f9fca47") req.Header.Set("origin", "https://fanyi.caiyunapp.com") req.Header.Set("os-type", "web") req.Header.Set("os-version", "") req.Header.Set("referer", "https://fanyi.caiyunapp.com/") req.Header.Set("sec-ch-ua", `"Not/A)Brand";v="99", "Microsoft Edge";v="115", "Chromium";v="115"`) req.Header.Set("sec-ch-ua-mobile", "?0") req.Header.Set("sec-ch-ua-platform", `"Windows"`) req.Header.Set("sec-fetch-dest", "empty") req.Header.Set("sec-fetch-mode", "cors") req.Header.Set("sec-fetch-site", "cross-site") req.Header.Set("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/115.0.0.0 Safari/537.36 Edg/115.0.1901.203") req.Header.Set("x-authorization", "token:qgemv4jr1y38jyq6vhvi") resp, err := client.Do(req) // 发送请求 if err != nil { log.Fatal(err) } defer resp.Body.Close() // resp.Body 也是个流,为了防止资源泄露,需要手动关闭流,defer在函数结束之后,从下往上触发 bodyText, err := io.ReadAll(resp.Body) // 从流中读入数据 if err != nil { log.Fatal(err) } fmt.Printf("%s\n", bodyText) // 打印出JSON字符串 }
-
-
构造结构体 生成request body(目的是和JSON的字段对应,使得可以序列化)
接收一个普通的 Go 值(例如结构体、切片、映射等),并返回一个字节切片(
[]byte
)表示 JSON 编码后的数据type Dictrequest struct{ Transtype string `json:"trans_type"` Source string `json:"source"` UserID string `json:"user_id"` }
-
解析 response body
构造结构体,字段和body对应,把得到的JSON数据反序列化成结构体
解决方法:代码生成工具 JSON转Golang Struct - 在线工具 - OKTools
将preview的JSON复制过来转换为嵌套
修改如下
/* * @Author: NEFU AB-IN * @Date: 2023-08-23 10:35:07 * @FilePath: \GoTest\5\5.go * @LastEditTime: 2023-08-23 12:34:19 */ package main import ( "encoding/json" "fmt" "io" "log" "net/http" "strings" ) type Dictrequest struct { Transtype string `json:"trans_type"` Source string `json:"source"` UserID string `json:"user_id"` } type DictResponse struct { Rc int `json:"rc"` Wiki struct { } `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 main() { client := &http.Client{} request := DictRequest{TransType: "en2zh", Source: "good"} buf, err := json.Marshal(request) if err != nil { log.Fatal(err) } var data = bytes.NewReader(buf) // 因为JSON解析完是byte数组,所以改成bytes.NewReader req, err := http.NewRequest("POST", "https://api.interpreter.caiyunai.com/v1/dict", data) if err != nil { log.Fatal(err) } //client := &http.Client{} //var data = strings.NewReader(`{"trans_type":"en2zh","source":"good"}`) //req, err := http.NewRequest("POST", "https://api.interpreter.caiyunai.com/v1/dict", data) //if err != nil { // log.Fatal(err) //} req.Header.Set("authority", "api.interpreter.caiyunai.com") req.Header.Set("accept", "application/json, text/plain, */*") req.Header.Set("accept-language", "zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6") req.Header.Set("app-name", "xy") req.Header.Set("content-type", "application/json;charset=UTF-8") req.Header.Set("device-id", "313abb19c54ae93fa733afae2f9fca47") req.Header.Set("origin", "https://fanyi.caiyunapp.com") req.Header.Set("os-type", "web") req.Header.Set("os-version", "") req.Header.Set("referer", "https://fanyi.caiyunapp.com/") req.Header.Set("sec-ch-ua", `"Not/A)Brand";v="99", "Microsoft Edge";v="115", "Chromium";v="115"`) req.Header.Set("sec-ch-ua-mobile", "?0") req.Header.Set("sec-ch-ua-platform", `"Windows"`) req.Header.Set("sec-fetch-dest", "empty") req.Header.Set("sec-fetch-mode", "cors") req.Header.Set("sec-fetch-site", "cross-site") req.Header.Set("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/115.0.0.0 Safari/537.36 Edg/115.0.1901.203") req.Header.Set("x-authorization", "token:qgemv4jr1y38jyq6vhvi") resp, err := client.Do(req) if err != nil { log.Fatal(err) } defer resp.Body.Close() bodyText, err := io.ReadAll(resp.Body) // 返回的byte数组 if err != nil { log.Fatal(err) } var dictResponse DictResponse err = json.Unmarshal(bodyText, &dictResponse) if err != nil { log.Fatal(err) } fmt.Printf("%#v\n", dictResponse) // 最详细的打印出来 }
-
修改代码(不再固定查询)
- 修改 main 函数,编写简单的main函数,用于接收用户输入的单词,并调用query函数进行查询。
- 将代码主体改成一个
query
函数,用于查询单词的释义,并通过参数传递要查询的单词。 - 使用
for range
循环迭代dictResponse.Dictionary.Explanations
,打印出查询结果中的释义部分,即只查询想要的东西 - 在
query
函数中增加了对API返回状态码的检查,如果不是200
,会打印错误信息并退出程序。
最终版
/* * @Author: NEFU AB-IN * @Date: 2023-08-23 10:35:07 * @FilePath: \GoTest\5\5.go * @LastEditTime: 2023-08-23 15:20:30 */ package main import ( "bytes" "encoding/json" "fmt" "io" "log" "net/http" "os" ) type DictRequest struct { TransType string `json:"trans_type"` Source string `json:"source"` UserID string `json:"user_id"` } type DictResponse struct { Rc int `json:"rc"` Wiki struct { } `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 main() { if len(os.Args) != 2 { fmt.Fprintf(os.Stderr, `usage: simpleDict WORD example: simpleDict hello `) os.Exit(1) } word := os.Args[1] // fmt.Println(os.Args[0]) query(word) } 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("authority", "api.interpreter.caiyunai.com") req.Header.Set("accept", "application/json, text/plain, */*") req.Header.Set("accept-language", "zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6") req.Header.Set("app-name", "xy") req.Header.Set("content-type", "application/json;charset=UTF-8") req.Header.Set("device-id", "313abb19c54ae93fa733afae2f9fca47") req.Header.Set("origin", "https://fanyi.caiyunapp.com") req.Header.Set("os-type", "web") req.Header.Set("os-version", "") req.Header.Set("referer", "https://fanyi.caiyunapp.com/") req.Header.Set("sec-ch-ua", `"Not/A)Brand";v="99", "Microsoft Edge";v="115", "Chromium";v="115"`) req.Header.Set("sec-ch-ua-mobile", "?0") req.Header.Set("sec-ch-ua-platform", `"Windows"`) req.Header.Set("sec-fetch-dest", "empty") req.Header.Set("sec-fetch-mode", "cors") req.Header.Set("sec-fetch-site", "cross-site") req.Header.Set("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/115.0.0.0 Safari/537.36 Edg/115.0.1901.203") req.Header.Set("x-authorization", "token:qgemv4jr1y38jyq6vhvi") resp, err := client.Do(req) if err != nil { log.Fatal(err) } defer resp.Body.Close() bodyText, err := io.ReadAll(resp.Body) // 返回的byte数组 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.Printf("%#v\n", dictResponse) // 最详细的打印出来 fmt.Println(word, "UK:", dictResponse.Dictionary.Prons.En, "US:", dictResponse.Dictionary.Prons.EnUs) for _, item := range dictResponse.Dictionary.Explanations { fmt.Println(item) } }