选题二:GO语言工程实践课后作业 | 青训营

120 阅读5分钟

Go语言项目实践笔记

项目一:猜数游戏

项目简介

猜数游戏是一个简单的命令行游戏,计算机随机生成一个0到99的整数,玩家需要猜测这个整数是多少。游戏会根据玩家的猜测给出提示,直到猜中为止。

代码分析

package main

import (
	"bufio"
	"fmt"
	"math/rand"
	"os"
	"strconv"
	"strings"
	"time"
)

func main() {
	// 生成随机数种子
	maxNum := 100
	rand.Seed(time.Now().UnixNano())
	secretNumber := rand.Intn(maxNum)

	fmt.Println("Please input your guess")
	reader := bufio.NewReader(os.Stdin)
	for {
		// 读取玩家输入
		input, err := reader.ReadString('\n')
		if err != nil {
			fmt.Println("An error occurred while reading input. Please try again.", err)
			continue
		}
		input = strings.Trim(input, "\r\n")

		// 将输入转换成整数
		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
		}
	}
}

代码说明

  • 程序开始部分使用rand.Seed函数设定随机数种子,以当前时间作为种子,确保每次运行游戏随机数都不同。
  • 使用rand.Intn生成一个0到99的随机整数作为猜测目标。
  • 使用bufio.NewReader读取玩家输入的字符串。
  • 使用strings.Trim函数移除输入字符串中的换行符。
  • 使用strconv.Atoi函数将输入字符串转换为整数。
  • 根据玩家猜测结果,给出相应的提示,直到猜中为止。

课后实践作业思路

作业要求是简化代码实现,使用fmt的Scan方法,这里我采用fmt.Scanln方法就行,使用Scanln方法可以在接受一个参数的时候以回车结束接收。 只需要在for循环外面声明一个guess参数,之后在每次猜数的时候运行

fmt.Scanln(&guess)

即可

项目二:翻译词典

项目简介

翻译词典是一个命令行工具,可以将英文单词翻译为中文,使用了彩云翻译的API。

代码分析

package main

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io"
	"log"
	"net/http"
	"os"
)

type DictResponse struct {
	// 省略其他字段
}

type DictRequest struct {
	TransType string `json:"trans_type"`
	Source    string `json:"source"`
	UserId    string `json:"user_id"`
}

func main() {
	if len(os.Args) < 2 {
		fmt.Fprintf(os.Stderr, `usage:simpleDict WORD example:simpleDict hello`)
	} else {
		for i, j := range os.Args {
			if i != 0 {
				query(j)
			}
		}
	}
}

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)
	// 省略设置请求头部分
	resp, err := client.Do(req)
	if err != nil {
		log.Fatal(err)
	}
	defer resp.Body.Close()
	bodyText, err := io.ReadAll(resp.Body)
	if err != nil {
		log.Fatal(err)
	}
	var dictResponse DictResponse
	err = json.Unmarshal(bodyText, &dictResponse)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println()
	fmt.Println(word, "UK:", dictResponse.Dictionary.Prons.En, "US:", dictResponse.Dictionary.Prons.EnUs)
	for _, i := range dictResponse.Dictionary.Explanations {
		fmt.Println(i)
	}
}

代码说明

  • 在命令行输入一个英文单词作为参数。
  • 使用http.Client进行网络请求,调用彩云翻译的API进行单词翻译。
  • 使用json.Marshal将请求参数结构体序列化为JSON格式的数据,并使用bytes.NewReader创建请求的数据体。
  • 使用http.NewRequest创建POST请求,并设置请求头部信息。
  • 使用io.ReadAll读取响应的JSON数据,并使用json.Unmarshal将JSON解析为结构体对象。
  • 输出翻译结果,包括英式发音和美式发音,以及单词释义。

课后实践作业思路

课后作业要求使用另一个翻译引擎的api实现同样的操作,我这里选择了百度翻译的引擎,但是并未在返回结果里发现音标数据,但是也可以实现其他操作。 思路与使用彩云小译的api大差不差,都是先去网页控制台查看翻译的请求格式

进行翻译之后在控制台找到post请求method的dict请求,然后将其response响应标头复制成curl格式。

之后在转换网站Convert curl to Go (curlconverter.com)将curl转换成go的代码,会自动根据curl格式生成一份可以生成同样请求的go代码。

请求数据序列化marshal成json

将写死的数据抽象成对应的结构体,之后将结构体对象用json包序列化成json,再传到请求里面。

请求之后用变量bodyTest接住得到的结果,再反序列化Unmarshal成我们想要的结果

通过浏览器查看预览格式生成对应结构体

在浏览器查看返回结果的预览结果,之后复制进JSON转Golang Struct - 在线工具 - OKTools网站得到结构对应的结构体,就能在json反序列化的时候用这个结构体接住得到的结果。

项目三:SOCKS5代理

项目简介

SOCKS5代理是一个基于SOCKS5协议的代理服务器,可以用来转发网络请求,实现网络代理功能。

代码分析

package main

import (
	"log"
	"net"
)

func main() {
	// 创建一个TCP server,监听在本地的1080端口
	server, err := net.Listen("tcp", "127.0.0.1:1080")
	if err != nil {
		panic(err)
	}
	for {
		// 接受客户端的连接
		client, err := server.Accept()
		if err != nil {
			log.Print("Accept failed %v", err)
			continue
		}
		// 使用goroutine处理每个连接
		go process(client)
	}
}

func process(conn net.Conn) {
	defer conn.Close()
	// 创建一个读取器
	reader := bufio.NewReader(conn)
	for {
		// 读取客户端发送的数据
		by, err := reader.ReadByte()
		if err != nil {
			break
		}
		// 将数据原样写回客户端,实现简单的回显代理
		_, err = conn.Write([]byte{by})
		if err != nil {
			break
		}
	}
}

代码说明

  • 创建一个TCP服务器,监听在本地的1080端口,等待客户端连接。
  • 使用server.Accept()接受客户端的连接,返回

一个与客户端连接的net.Conn对象。

  • 为每个客户端连接启动一个goroutine,使用process函数处理客户端的请求。
  • process函数读取客户端发送的数据,并将数据原样写回客户端,实现简单的回显代理功能。

总结

以上三个项目涵盖了Go语言的基础知识和常用库的使用,包括随机数生成、网络请求、JSON数据处理、命令行参数解析、文件读写等。通过这些项目的实践,我们可以更好地理解Go语言的特性和语法,培养编程能力,提高代码质量。同时,这些项目也可以作为基础,进一步拓展和完善,开发更加复杂、功能更加丰富的Go语言应用。