golang中post请求

开发中我们可能会遇到请求第三方接口的需求。比如我需要调用百度翻译或者谷歌翻译,翻译一段英文并输出中文。

1、目录结构

.
├── go.mod
├── go.sum
├── main.go
└── transfer
    ├── transfer.go
    ├── transfer_baidu.go
    └── transfer_goog.go

2、思路

首先我们需要输入一段英文,然后调用一个方法,返回结果中会带上错误和翻译之后的结构,向下面这样

package main

import (
	"fmt"
	"go-demo/crawlblog/transfer"
)

var transferBase transfer.TransferBase

func main() {
	enText := `Setup RabbitMQ:
	You can easily set up rabbitMq on your local machine or any cloud instance.

	Run-on docker: You can easily run rabbitMq if you have docker setup on your local instance using this command.
	`

	transferBase = &transfer.TransferBaidu{}
	res, err := transferBase.TranslateText("zh", enText)
	if err != nil {
		fmt.Println(err)
		return
	}

	fmt.Println(res)
}

因此我们需要定义一个通用的接口和方法,可以灵活的切换翻译软件。比如我现在用的是百度翻译,但是后面如果有谷歌翻译的需求,我只需要增加一个类,实现这个接口,不用修改之前的代码。

所以我定义了一个接口,里面有一个 TranslateText 翻译的方法,然后定义了返回结构体

package transfer

type TransferBase interface {
	TranslateText(targetLanguage, text string) (*Result, error)
}

type TransRes struct {
	Src string `json:"src"`
	Dst string `json:"dst"`
}

type Result struct {
	From        string     `json:"from"`
	To          string     `json:"to"`
	TransResult []TransRes `json:"trans_result"`
}

接下来新增一个 transfer_baidu.go 文件,里面实现上面的方法。主要是调用百度接口的请求

package transfer

import (
	"context"
	"crypto/md5"
	"encoding/hex"
	"encoding/json"
	"io/ioutil"
	"math/rand"
	"net/http"
	"net/url"
	"strconv"
	"strings"
)

const (
	APPID     = "***"
	APPSECRET = "***"
)

type TransferBaidu struct {
}

func (t *TransferBaidu) TranslateText(targetLanguage, text string) (*Result, error) {
	// text := "The Go Gopher is cute"
	ctx := context.Background()

	salt := strconv.Itoa(rand.Int())
	sign := getSign(text, salt)

	baseUrl := "https://fanyi-api.baidu.com/api/trans/vip/translate"
	uri := url.Values{}
	uri.Set("q", text)
	uri.Set("from", "auto")
	uri.Set("to", targetLanguage)
	uri.Set("appid", APPID)
	uri.Set("salt", salt)
	uri.Set("sign", sign)
	reqBody := strings.NewReader(uri.Encode())
	req, err := http.NewRequestWithContext(ctx, http.MethodPost, baseUrl, reqBody)
	if err != nil {
		return nil, err
	}

	req.Header.Add("Content-Type", "application/x-www-form-urlencoded")

	client := http.Client{}
	response, err := client.Do(req)
	if err != nil {
		return nil, err
	}
	defer response.Body.Close()

	content, err := ioutil.ReadAll(response.Body)
	if err != nil {
		return nil, err
	}

	contentStruct := &Result{}
	err = json.Unmarshal(content, contentStruct)
	if err != nil {
		return nil, err
	}
	return contentStruct, nil

}

func getSign(q, salt string) string {
	str := APPID + q + salt + APPSECRET
	md5Str := md5.Sum([]byte(str))
	return hex.EncodeToString(md5Str[:])
}

我们执行下代码:

go run main.go
&{en zh [{Setup RabbitMQ: 设置RabbitMQ:} {You can easily set up rabbitMq on your local machine or any cloud instance. 您可以在本地计算机或任何云实例上轻松设置rabbitMq。} {Run-on docker: You can easily run rabbitMq if you have docker setup on your local instance using this command. Runondocker:如果使用此命令在本地实例上设置了docker,则可以轻松运行rabbitMq。}]}

可以看到,之前的英文有翻译成中文了。