这是我参与「第三届青训营-后端场」笔记创作活动的第1篇笔记。
Golang基础实战小项目
猜数字游戏
首先我们需要生成随机数:
maxNum := 100
secretNumber := rand.Intn(maxNum)
fmt.Println("The secret number is ", secretNumber)
这里用到了math/rand包里的Intn函数,maxNum参数会随机生成0-maxNum的一个数字
这里我们可以发现,虽然已经生成了随机数,但是当我们重复执行3次程序后,每次执行的结果总是相同,如果想要每次生成的数字都不相同,需要我们设置一个随机数种子,一般做法是使用一个时间戳来初始化随机数种子:
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)
input, err := reader.ReadString('\n')
if err != nil {
fmt.Println("An error occured while reading input. Please try again", err)
return
}
//去除换行符
input = strings.TrimSuffix(input, "\n")
//转化为数字
guess, err := strconv.Atoi(input)
if err != nil {
fmt.Println("Invalid input. Please enter an integer value")
return
}
fmt.Println("You guess is", guess)
但是这段代码在windows10运行的时候会出现这种错误
出现这个问题的原因是因为win10平台在你按回车之后,会在参数的末尾加上\r\n作为换行符,而你的代码只处理了\n的这种情况,没有考虑\r\n这种情况。
解决方法如下:
input = strings.TrimSuffix(input, "\r\n")
只需再添加一个'\r'即可
最后只需循环判断数字是否正确即可: 完整代码:
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")
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.TrimSuffix(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
}
}
}
运行效果:
在线词典
命令行在线词典原理就是,通过Golang发起请求,调用现成的翻译平台的接口来获取单词数据,这里分别采用百度翻译的接口和有道翻译的接口:
百度翻译
首先是百度翻译,这里我是直接调用百度官方文档的接口,
req, err := http.NewRequest("POST", "https://fanyi-api.baidu.com/api/trans/vip/translate", data)
想要使用这个接口需要自行先注册一个开发者账号,获取appid和secret
根据上表把参数拼接在data里面,example:
q=apple&from=en&to=zh&appid=2015063000000001&salt=1435660288&sign=f89f9594663708c1605f3d736d01d2d4
也可以发起GET请求,只需把参数拼接在url即可。另外,请求最好设置请求头,以免请求失败,发起请求成功后会获得一个响应,响应的json格式如下:
{
"from": "en",
"to": "zh",
"trans_result": [
{
"src": "apple",
"dst": "苹果"
}
]
}
在golang里我们可以定义一个结构体来接收这个返回响应:
type BaiduResponse struct {
From string `json:"from"`
To string `json:"to"`
TransResult []struct {
Src string `json:"src"`
Dst string `json:"dst"`
} `json:"trans_result"`
}
获得响应,再获取我们想要的数据
//获得返回的响应,类型为*http.Response
resp, err := client.Do(req)
if err != nil {
log.Fatal(err)
}
defer resp.Body.Close()
//读取进bodyText,类型为[]byte
bodyText, err := ioutil.ReadAll(resp.Body)
if err != nil {
log.Fatal(err)
}
var baiduResponse BaiduResponse
//json序列化
err = json.Unmarshal(bodyText, &baiduResponse)
if err != nil {
//打印错误日志
log.Fatal(err)
}
fmt.Println("百度翻译结果:", baiduResponse.TransResult[0].Dst)
执行效果:
有道翻译
接着再来尝试一下有道翻译,这次是直接通过分析网站上发起的请求来获取我们想要的数据,可通过这种方法直接复制请求
通过快速生成代码网站来生成golang代码:(Convert curl commands to code (curlconverter.com))
但是当我们多次请求时会发现,每一次请求的参数sign,salt和lts都是不一样的
根据查找资料可知,这里的salt是一个时间戳,lts是在salt的基础上加上10以内的随机生成数,而sign则是通过拼接几个参数生成的md5密文,具体生成如下:
//生成时间戳
salt := strconv.FormatInt(time.Now().Unix(), 10)
//加上一个10以内的随机数
lts := salt + strconv.Itoa(rand.Intn(10))
//word为要翻译的单词
code := md5.Sum([]byte("fanyideskweb" + word + salt + "Y2FYu%TNSbMCxc3t2u^XT"))
sign := fmt.Sprintf("%x", code)
最后将数据拼接成请求表单即可,即可查询任意单词
请求之后会获得一个响应,这里同样可以使用快速生成代码网站来生成golang结构体 ,先复制响应
通过此网站快速生成golang结构体代码:JSON转Golang Struct - 在线工具 - OKTools
最后进行类似于百度翻译来操作返回的response即可获得我们想要的参数
运行效果: