目标
用golang写一个命令行的翻译工具,在命令行输入以下命令:
输出以下结果:
1 2 3 4 5 6 7 8 9 10
| hello [həˈləʊ]
- 你好
1. Hello Android 创建,创立,建立 2. Hello Neighbor 你好邻居,你好 3. Hello English 新纪元小学英语,学英语,律动欢唱学英语
|
接收参数
创建目录和main.go,接收命令行参数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| package main
import ( "fmt" "os" )
func main() { args := os.Args words := args[1:] if len(words) == 0 { return } fmt.Println("words: ", words) }
|
找一个翻译API
我这里用的是有道的API
1
| http://fanyi.youdao.com/openapi.do?keyfrom=node-fanyi&key=<your key here>&type=data&doctype=json&version=1.1&q=hello
|
创建翻译包
我把具体的翻译逻辑放到一个叫translate的包中,基于有道翻译的逻辑我写在youdao.go文件中
1 2 3 4 5 6 7
| package translate
func Youdao(words string) (string, error) { return "", nil }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| package main
import ( "fmt" "os" "log" "strings"
"./translate" )
func main() { args := os.Args words := strings.Join(args[1:], " ") if len(words) == 0 { log.Fatal("empty params") } translate, err := translate.Youdao(words) if err != nil { log.Fatal(err) } fmt.Println(translate) }
|
向有道API发起请求
使用golang内置的net/http包发起http请求
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| package translate
import ( "fmt" "strings" "net/http" "ioutil" )
const youdaoApi = "http://fanyi.youdao.com/openapi.do?keyfrom=node-fanyi&key=<your key here>&type=data&doctype=json&version=1.1&q=${word}"
func Youdao(words string) (string, error) { fmt.Println("youdao: ", words) url := strings.replace(youdaoApi, "${word}", words, 1) res, err := http.Get(url) if err != nil { return "", err } defer res.Body.Close() body, err := ioutil.ReadAll(res.Body) if err != nil { return "", err } fmt.Println(body) }
|
解析json数据
golang已经内置了用于解析json数据的工具,我们只需要按照json数据的格式创建对应的struct。
有道API返回的json数据格式如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| { "translation": ["你好"], "basic": { "us-phonetic": "helˈō", "phonetic": "həˈləʊ", "uk-phonetic": "həˈləʊ", "explains": ["n. 表示问候, 惊奇或唤起注意时的用语", "int. 喂;哈罗", "n. (Hello)人名;(法)埃洛"] }, "query": "hello", "errorCode": 0, "web": [{ "value": ["创建", "创立", "建立"], "key": "Hello Android" }, { "value": ["你好邻居", "你好"], "key": "Hello Neighbor" }, { "value": ["新纪元小学英语", "学英语", "律动欢唱学英语"], "key": "Hello English" }] }
|
在youdao.go中创建对应的struct
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| type YoudaoData struct { Translation []string `json:"translation"` Basic YoudaoBasic `json:"basic"` Query string `json:"query"` ErrorCode string `json:"errorCode"` Web []YoudaoWebItem `json:"web"` }
type YoudaoBasic struct { UsPhonetic string `json:"us-phonetic"` Phonetic string `json:"phonetic"` UkPhonetic string `json:"uk-phonetic"` Explains []string `json:"explains"` }
type YoudaoWebItem struct { Value []string `json:"value"` Key string `json:"key"` }
|
修改Youdao(words string)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| func Youdao(words string) (YoudaoData, error) { var jsonData YoudaoData url := strings.replace(youdaoApi, "${word}", words, 1) res, err := http.Get(url) if err != nil { return jsonData, err } defer res.Body.Close() body, err := ioutil.ReadAll(res.Body) if err != nil { return jsonData, err } json.Unmarshal(body, &jsonData) return jsonData, nil }
|
现在可以在命令行看到结果了
1
| {[你好] {helˈō həˈləʊ həˈləʊ [n. 表示问候, 惊奇或唤起注意时的用语 int. 喂;哈罗 n. (Hello)人名;(法)埃洛]} hello [{[创建 创立 建立] Hello Android} {[你好邻居 你好] Hello Neighbor} {[新纪元小学英语 学英语 律动欢唱学英语] Hello English}]}
|
这样的结果不是我们想要的,我们希望在fmt.Println(translate)
是数据能自动带上格式。
数据格式化输出
就像Java里的toString方法一样,我们只需要让struct实现String()接口就可以修改输出内容
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| func (data YoudaoData) String() string { phonetic := fmt.Sprintf("%s [%s]\n", data.Query, data.Basic.Phonetic) var explains string for _, val := range data.Translation { explains += fmt.Sprintf("- %s\n", val) } var examples string for index, item := range data.Web { examples += fmt.Sprintf("%d. %s\n %s\n", index+1, item.Key, strings.Join(item.Value, ",")) } return fmt.Sprintf(` %s %s %s `, phonetic, explains, examples) }
|
再次运行go run main.go hello
,输出为
1 2 3 4 5 6 7 8 9 10
| hello [həˈləʊ]
- 你好
1. Hello Android 创建,创立,建立 2. Hello Neighbor 你好邻居,你好 3. Hello English 新纪元小学英语,学英语,律动欢唱学英语
|
感觉目的达到了。
Bug
查看有道的API文档,发现这个API是智能翻译,意思是输入什么语言都可以。
我们试试go run main.go 你好
,输出了乱码加空白
既然我们是调用的http的get请求,那么在传递特殊字符时应该先encode一下,修改Youdao(words string)
方法
1 2 3 4 5 6 7
| func Youdao(words string) (YoudaoData, error) { var jsonData YoudaoData url := strings.Replace(youdao, "${word}", url.QueryEscape(words), 1) ...
}
|
再试一次go run main.go 你好
1 2 3 4 5 6 7 8 9 10
| 你好 []
- hello
1. 老师你好 Teacher Kim Bong-du,My Teacher Mr Kim,SALVE MAGISTER 2. 你好嘢 Her Fatal Ways,HIS FATAL WAYS,wvkj 3. 你好总统 Alo Presidente
|
感觉好像可以了。