欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

golang 如何實(shí)現(xiàn)HTTP代理和反向代理

 更新時(shí)間:2021年05月07日 08:58:46   作者:貓哭  
這篇文章主要介紹了golang 實(shí)現(xiàn)HTTP代理和反向代理的操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧

代理的核心功能可以用一句話概括:接受客戶端的請(qǐng)求,轉(zhuǎn)發(fā)到后端服務(wù)器,獲得應(yīng)答之后返回給客戶端。

代理的功能有很多,事實(shí)上整個(gè)互聯(lián)網(wǎng)到處都充斥著代理服務(wù)器。如果所有的 HTTP 訪問(wèn)都是客戶端和服務(wù)器端直接進(jìn)行的話,我們的網(wǎng)絡(luò)不僅會(huì)變得緩慢,而且性能會(huì)大打折扣。

代理服務(wù)器根據(jù)不同的配置和使用,可能會(huì)有不同的功能,這些功能主要包括:

內(nèi)容過(guò)濾:代理可以根據(jù)一定的規(guī)則限制某些請(qǐng)求的連接。比如有些公司會(huì)設(shè)置內(nèi)部網(wǎng)絡(luò)無(wú)法訪問(wèn)某些購(gòu)物、游戲網(wǎng)站,或者學(xué)校的網(wǎng)絡(luò)不讓學(xué)生訪問(wèn)色情暴力的網(wǎng)站等

節(jié)省成本:代理服務(wù)器可以作為緩存使用,對(duì)于某些資源只需要第一次訪問(wèn)的時(shí)候去下載,以后代理直接把緩存的結(jié)果返回給客戶端,節(jié)約網(wǎng)絡(luò)帶寬的開(kāi)銷

提高性能:通過(guò)代理服務(wù)器的緩存(比如 CDN)和負(fù)載均衡(比如 nginx lb)功能,服務(wù)器端可以加速請(qǐng)求的訪問(wèn),在更快的時(shí)間內(nèi)返回結(jié)果)

增加安全性:公司可以在內(nèi)網(wǎng)和外網(wǎng)之間通過(guò)代理進(jìn)行轉(zhuǎn)發(fā),這樣不僅對(duì)外隱藏了實(shí)現(xiàn)的細(xì)節(jié),而且可以在代理層對(duì)爬蟲、病毒性請(qǐng)求進(jìn)行過(guò)濾,保護(hù)內(nèi)部服務(wù)

所有的這些功能的實(shí)現(xiàn)都依賴于代理的特性,它可以在客戶端和服務(wù)器端做一些事情,根據(jù)代理做的事情不同,它的角色和功能也就不同。那么,代理具體可以做哪些事情呢?比如:

修改 HTTP 請(qǐng)求:url、header、body

過(guò)濾請(qǐng)求:根據(jù)一定的規(guī)則丟棄、過(guò)濾請(qǐng)求

決定轉(zhuǎn)發(fā)到哪個(gè)后端(可以是靜態(tài)定義的,也可以是動(dòng)態(tài)決定)

保存服務(wù)器的應(yīng)答,后續(xù)的請(qǐng)求可以直接使用保存的應(yīng)答

修改應(yīng)答:對(duì)應(yīng)答做一些格式的轉(zhuǎn)換,修改數(shù)據(jù),甚至返回完全不一樣的應(yīng)答數(shù)據(jù)

重試機(jī)制,如果后端服務(wù)器暫時(shí)無(wú)法響應(yīng),隔一段時(shí)間重試

……

正向代理和反向代理

代理可以分為正向代理和反向代理兩種。

正向代理需要客戶端來(lái)配置,一般來(lái)說(shuō)我們會(huì)通過(guò)瀏覽器或者操作系統(tǒng)提供的工具或者界面來(lái)配置。這個(gè)時(shí)候,代理對(duì)客戶端不是透明的,客戶端需要知道代理的地址并且手動(dòng)配置。配置了代理,瀏覽器在發(fā)送請(qǐng)求的時(shí)候會(huì)對(duì)報(bào)文做特殊的修改。

反向代理對(duì)客戶端是透明的,也就是說(shuō)客戶端一般不知道代理的存在,認(rèn)為自己是直接和服務(wù)器通信。我們大部分訪問(wèn)的網(wǎng)站就是反向代理服務(wù)器,反向代理服務(wù)器會(huì)轉(zhuǎn)發(fā)到真正的服務(wù)器,一般在反向代理這一層實(shí)現(xiàn)負(fù)載均衡和高可用的功能。而且這里也可以看到,客戶端是不會(huì)知道真正服務(wù)器端的 ip 地址和端口的,這在一定程度上起到了安全保護(hù)的作用。

代理服務(wù)器怎么知道目的服務(wù)器的地址?

在反向代理中,代理服務(wù)器要轉(zhuǎn)發(fā)的服務(wù)器地址都是事先知道的(包括靜態(tài)配置和動(dòng)態(tài)配置)。比如 使用 nginx 來(lái)配置負(fù)載均衡 。

而對(duì)于正向代理來(lái)說(shuō),客戶端可能訪問(wèn)的服務(wù)器地址是無(wú)法事先知道的。因?yàn)镠TTP 協(xié)議活動(dòng)在應(yīng)用層,它無(wú)法獲取網(wǎng)絡(luò)層(IP層)信息,那么該協(xié)議要有一個(gè)地方可以拿到這個(gè)信息。HTTP 中可能保存這個(gè)信息的地方有兩個(gè):URL 和 header。默認(rèn)情況下,HTTP 請(qǐng)求的 status line 有三部分組成:方法、uri 和協(xié)議版本,比如:

GET /index.html HTTP/1.0
User-Agent: gohttp 1.0

如果客戶端(比如瀏覽器)知道自己在通過(guò)正向代理進(jìn)行報(bào)文傳輸,那么它會(huì)在 status line 加上要訪問(wèn)服務(wù)器的真實(shí)地址。這個(gè)時(shí)候發(fā)送的報(bào)文是:

GET http://www.marys-antiques.com/index.html HTTP/1.0
User-Agent: gohttp 1.0

代理路徑

客戶端不管是通過(guò)代理服務(wù)器,還是直接訪問(wèn)后端服務(wù)器對(duì)于最終的結(jié)果是沒(méi)有區(qū)別的,也就是說(shuō)大多數(shù)情況下客戶端根本不關(guān)心它訪問(wèn)的到底是什么,只需要(準(zhǔn)確快速地)拿到想要的信息就夠了。但是有時(shí)候,我們還是希望知道請(qǐng)求到底在中間經(jīng)歷了哪些代理,比如用來(lái)調(diào)試網(wǎng)絡(luò)異常,或者做數(shù)據(jù)統(tǒng)計(jì),而 HTTP 協(xié)議也提供了響應(yīng)的功能。

雖然 RFC 2616 定義了 Via 頭部字段來(lái)跟蹤 HTTP 請(qǐng)求經(jīng)過(guò)的代理路徑,但在實(shí)際中用的更多的還是 X-Forwarded-For 字段, X-Forwarded-For 是 Squid 緩存代理服務(wù)軟件引入的,目前已經(jīng)在規(guī)范化在 RFC 7239 文檔。

X-Forwarded-For 頭部格式也比較簡(jiǎn)單,比如某個(gè)服務(wù)器接受到請(qǐng)求的對(duì)應(yīng)頭部可能是:

X-Forwarded-For: client, proxy1, proxy2

對(duì)應(yīng)的值有多個(gè)字段,每個(gè)字段代表中間的一個(gè)節(jié)點(diǎn),它們之間由逗號(hào)和空格隔開(kāi),從左到右距離當(dāng)前節(jié)點(diǎn)越來(lái)越近。

每個(gè)代理服務(wù)器會(huì)在 X-Forwarded-For 頭部填上前一個(gè)節(jié)點(diǎn)的 ip 地址,這個(gè)地址可以通過(guò) TCP 請(qǐng)求的 remote address 獲取。為什么每個(gè)代理服務(wù)器不填寫自己的 ip 地址呢?有兩個(gè)原因,如果由代理服務(wù)器填寫自己的 ip 地址,那么代理可以很簡(jiǎn)單地偽造這個(gè)地址,而上一個(gè)節(jié)點(diǎn)的 remote address 是根據(jù) TCP 連接獲取的(如果不建立正確的 TCP 連接是無(wú)法進(jìn)行 HTTP 通信的);另外一個(gè)原因是如果由當(dāng)前節(jié)點(diǎn)填寫 X-Forwarded-For ,那么很多情況客戶端無(wú)法判斷自己是否會(huì)通過(guò)代理的。

NOTE:

1、最終客戶端或者服務(wù)器端接受的請(qǐng)求, X-Forwarded-For 是沒(méi)有最鄰近節(jié)點(diǎn)的 ip 地址的,而這個(gè)地址可以通過(guò) remote address 獲取

2、每個(gè)節(jié)點(diǎn)(不管是客戶端、代理服務(wù)器、真實(shí)服務(wù)器)都可以隨便更改 X-Forwarded-For 的值,因此這個(gè)字段只能作為參考

代理服務(wù)器實(shí)現(xiàn)

這個(gè)部分我們會(huì)介紹如何用 golang 來(lái)實(shí)現(xiàn) HTTP 代理服務(wù)器,需要讀者了解一些 HTTP 服務(wù)器端編程的知識(shí)。

正向代理

按照我們之前介紹的代理原理,我們可以編寫出這樣的代碼:

package main
import (
	"fmt"
	"io"
	"net"
	"net/http"
	"strings"
)
type Pxy struct {}
func (p *Pxy) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
	fmt.Printf("Received request %s %s %s\n", req.Method, req.Host, req.RemoteAddr)
	transport :=  http.DefaultTransport
	// step 1
	outReq := new(http.Request)
	*outReq = *req // this only does shallow copies of maps
	if clientIP, _, err := net.SplitHostPort(req.RemoteAddr); err == nil {
		if prior, ok := outReq.Header["X-Forwarded-For"]; ok {
			clientIP = strings.Join(prior, ", ") + ", " + clientIP
		}
		outReq.Header.Set("X-Forwarded-For", clientIP)
	}
	// step 2
	res, err := transport.RoundTrip(outReq)
	if err != nil {
		rw.WriteHeader(http.StatusBadGateway)
		return
	}
	// step 3
	for key, value := range res.Header {
		for _, v := range value {
			rw.Header().Add(key, v)
		}
	}
	rw.WriteHeader(res.StatusCode)
	io.Copy(rw, res.Body)
	res.Body.Close()
}
func main() {
	fmt.Println("Serve on :8080")
	http.Handle("/", &Pxy{})
	http.ListenAndServe("0.0.0.0:8080", nil)
}

這段代碼比較直觀,只包含了最核心的代碼邏輯,完全按照最上面的代理圖例進(jìn)行組織。一共分成幾個(gè)步驟:

1、代理接收到客戶端的請(qǐng)求,復(fù)制了原來(lái)的請(qǐng)求對(duì)象,并根據(jù)數(shù)據(jù)配置新請(qǐng)求的各種參數(shù)(添加上 X-Forward-For 頭部等)

2、把新請(qǐng)求發(fā)送到服務(wù)器端,并接收到服務(wù)器端返回的響應(yīng)

3、代理服務(wù)器對(duì)響應(yīng)做一些處理,然后返回給客戶端

上面的代碼運(yùn)行之后,會(huì)在本地的 8080 端口啟動(dòng)代理服務(wù)。修改瀏覽器的代理為 127.0.0.1::8080 再訪問(wèn)網(wǎng)站,可以驗(yàn)證代理正常工作,也能看到它在終端打印出所有的請(qǐng)求信息。

雖然這段代碼非常簡(jiǎn)短,但是你可以添加更多的邏輯實(shí)現(xiàn)非常有用的功能。比如在請(qǐng)求發(fā)送之前進(jìn)行過(guò)濾,根據(jù)一定的規(guī)則直接阻止某些請(qǐng)求的訪問(wèn);或者對(duì)請(qǐng)求進(jìn)行限流,某個(gè)客戶端在一定的時(shí)間里執(zhí)行的請(qǐng)求有最大限額;統(tǒng)計(jì)請(qǐng)求的數(shù)據(jù)進(jìn)行分析等等。

這個(gè)代理目前不支持 HTTPS 協(xié)議,因?yàn)樗惶峁┝?HTTP 請(qǐng)求的轉(zhuǎn)發(fā)功能,并沒(méi)有處理證書和認(rèn)證有關(guān)的內(nèi)容。如果了解 HTTPS 協(xié)議的話,你會(huì)明白這種模式下是無(wú)法完成 HTTPS 握手的,雖然代理可以和真正的服務(wù)器建立連接(知道了對(duì)方的公鑰和證書),但是代理無(wú)法代表服務(wù)器和客戶端建立連接,因?yàn)榇矸?wù)器無(wú)法知道真正服務(wù)器的私鑰。

反向代理

編寫反向代理按照上面的思路當(dāng)然沒(méi)有問(wèn)題,只需要在第二步的時(shí)候,根據(jù)之前的配置修改 outReq 的 URL Host 地址可以了。不過(guò) Golang 已經(jīng)給我們提供了編寫代理的框架: httputil.ReverseProxy 。我們可以用非常簡(jiǎn)短的代碼來(lái)實(shí)現(xiàn)自己的代理,而且內(nèi)部的細(xì)節(jié)問(wèn)題都已經(jīng)被很好地處理了。

這部分我們會(huì)實(shí)現(xiàn)一個(gè)簡(jiǎn)單的反向代理,它能夠?qū)φ?qǐng)求實(shí)現(xiàn)負(fù)載均衡,隨機(jī)地把請(qǐng)求發(fā)送給某些配置好的后端服務(wù)器。使用 httputil.ReverseProxy 編寫反向代理最重要的就是實(shí)現(xiàn)自己的 Director 對(duì)象,這是 GoDoc 對(duì)它的介紹:

Director must be a function which modifies the request into a new request to be sent using Transport. Its response is then copied back to the original client unmodified. Director must not access the provided Request after returning.

簡(jiǎn)單翻譯的話, Director 是一個(gè)函數(shù),它接受一個(gè)請(qǐng)求作為參數(shù),然后對(duì)其進(jìn)行修改。修改后的請(qǐng)求會(huì)實(shí)際發(fā)送給服務(wù)器端,因此我們編寫自己的 Director 函數(shù),每次把請(qǐng)求的 Scheme 和 Host 修改成某個(gè)后端服務(wù)器的地址,就能實(shí)現(xiàn)負(fù)載均衡的效果(其實(shí)上面的正向代理也可以通過(guò)相同的方法實(shí)現(xiàn))??创a:

package main
import (
        "log"
        "math/rand"
        "net/http"
        "net/http/httputil"
        "net/url"
)
func NewMultipleHostsReverseProxy(targets []*url.URL) *httputil.ReverseProxy {
        director := func(req *http.Request) {
                target := targets[rand.Int()%len(targets)]
                req.URL.Scheme = target.Scheme
                req.URL.Host = target.Host
                req.URL.Path = target.Path
        }
        return &httputil.ReverseProxy{Director: director}
}
func main() {
        proxy := NewMultipleHostsReverseProxy([]*url.URL{
                {
                        Scheme: "http",
                        Host:   "localhost:9091",
                },
                {
                        Scheme: "http",
                        Host:   "localhost:9092",
                },
        })
        log.Fatal(http.ListenAndServe(":9090", proxy))
}

我們讓代理監(jiān)聽(tīng)在 9090 端口,在后端啟動(dòng)兩個(gè)返回不同響應(yīng)的服務(wù)器分別監(jiān)聽(tīng)在 9091 和 9092 端口,通過(guò) curl 訪問(wèn),可以看到多次請(qǐng)求會(huì)返回不同的結(jié)果。

➜  curl http://127.0.0.1:9090
116064a9eb83
➜  curl http://127.0.0.1:9090
8f7ccc11718f

同樣的,這段代碼也只是一個(gè) demo,存在著很多問(wèn)題,比如沒(méi)有錯(cuò)誤處理機(jī)制,如果后端某個(gè)服務(wù)器掛了,代理會(huì)返回 502 錯(cuò)誤,更好的做法是把請(qǐng)求轉(zhuǎn)發(fā)到另外的可用服務(wù)器。當(dāng)然也可以添加更多的特性讓它更好用,比如動(dòng)態(tài)地添加后端服務(wù)器列表;根據(jù)后端服務(wù)器的負(fù)載情況進(jìn)行負(fù)載轉(zhuǎn)發(fā)等等。

補(bǔ)充:golang 超簡(jiǎn)單實(shí)現(xiàn)反向代理(nginx 端口轉(zhuǎn)發(fā) Proxy)

100行你就可以做到類似nginx帶自動(dòng)更新的端口轉(zhuǎn)發(fā)功能

總共就2個(gè)文件,一個(gè)main(總行數(shù)128行),一個(gè)配置文件

main:

里面的json解析和log可以忽略

package main 
import (
	"github.com/weimingjue/json"
	utils2 "goProxy/utils"
	"goService/utils"
	"io/ioutil"
	"net"
	"net/http"
	"net/http/httputil"
	"net/url"
	"os"
	"strings"
	"sync"
	"time"
)
 
var (
	projectDir, _         = os.Getwd()
	fileName              = projectDir + "/domain.config"
	readFileTime    int64 = 0  //讀取文件的時(shí)間
	fileChangedTime int64 = 0  //文件修改時(shí)間
	domainData      [][]string //[{***.gq,8080,http://127.0.0.1:8080/}]
	duPeiZhiSuo     sync.Mutex //讀配置鎖
)
 
// 獲取反向代理域名
func getProxyUrl(reqDomain string) string {
	checkFile()
 
	for _, dms := range domainData {
		if strings.Index(reqDomain, dms[0]) >= 0 {
			return dms[2]
		}
	}
	return domainData[0][2]
}
 
//讀取配置文件
//域名:端口號(hào),未知域名默認(rèn)用第一個(gè)
func checkFile() {
	nowTime := time.Now().Unix()
	if nowTime-readFileTime < 300 {
		return
	}
	//每5分鐘判斷文件是否修改
	domainFile, _ := os.OpenFile(fileName, os.O_WRONLY|os.O_APPEND, 0)
	info, _ := domainFile.Stat()
	if info.ModTime().Unix() == fileChangedTime {
		return
	}
	duPeiZhiSuo.Lock()
	defer duPeiZhiSuo.Unlock()
	domainFile, _ = os.OpenFile(fileName, os.O_WRONLY|os.O_APPEND, 0) //加鎖再來(lái)一遍,防止重入
	info, _ = domainFile.Stat()
	changedTime := info.ModTime().Unix()
	if changedTime == fileChangedTime {
		return
	}
 
	//文件改變
 
	//重置數(shù)據(jù)
	readFileTime = nowTime
	fileChangedTime = changedTime
	domainData = [][]string{}
 
	bytes, _ := ioutil.ReadFile(fileName)
	split := strings.Split(string(bytes), "\n")
 
	for _, domainInfo := range split {
		dLen := len(domainInfo)
		if dLen < 8 || dLen > 20 { //忽略錯(cuò)誤信息
			continue
		}
		domainItems := strings.Split(domainInfo, ":")
		if len(domainItems) != 2 || len(domainItems[0]) < 3 || len(domainItems[1]) < 2 {
			continue
		}
		if utils.EndWidth(domainItems[1], "/") {
			domainItems = append(domainItems, "http://127.0.0.1:"+domainItems[1])
		} else {
			domainItems = append(domainItems, "http://127.0.0.1:"+domainItems[1]+"/")
		}
		domainData = append(domainData, domainItems)
	}
 
	domainSt, _ := json.Marshal(domainData)
	utils2.MyLogProxyI("配置已修改:" + string(domainSt))
}
 
//獲取主機(jī)名
func getHost(req *http.Request) string {
	if req.Host != "" {
		if hostPart, _, err := net.SplitHostPort(req.Host); err == nil {
			return hostPart
		}
		return req.Host
	}
	return "localhost"
}
 
func handleRequestAndRedirect(res http.ResponseWriter, req *http.Request) {
	host := getHost(req)
	proxyUrl := getProxyUrl(host)
	url2, _ := url.Parse(proxyUrl)
	utils2.MyLogProxyI("請(qǐng)求域名:" + host + ",轉(zhuǎn)到:" + proxyUrl)
 
	// create the reverse proxy
	proxy := httputil.NewSingleHostReverseProxy(url2)
 
	// Update the headers to allow for SSL redirection
	req.URL.Host = url2.Host
	req.URL.Scheme = url2.Scheme
	req.Header.Set("X-Forwarded-Host", req.Header.Get("Host"))
	req.Host = url2.Host
 
	// Note that ServeHttp is non blocking and uses a go routine under the hood
	proxy.ServeHTTP(res, req)
}
 
func main() {
	http.HandleFunc("/", handleRequestAndRedirect)
	if err := http.ListenAndServe(":80", nil); err != nil {
		utils.MyLogE("Proxy監(jiān)聽(tīng)80端口錯(cuò)誤:" + err.Error())
		panic(err)
	}
}

domain.config:

***為自己的域名,":"后面是需要轉(zhuǎn)發(fā)的端口,不用寫http://,任何地方都不能有空格

wang.gq:8080
***.aa:8081/

代碼寫的是相對(duì)目錄請(qǐng)到當(dāng)前目錄執(zhí)行"go run main.go",愉快的轉(zhuǎn)發(fā)從現(xiàn)在開(kāi)始

以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教。

相關(guān)文章

  • 詳解Golang中Context的三個(gè)常見(jiàn)應(yīng)用場(chǎng)景

    詳解Golang中Context的三個(gè)常見(jiàn)應(yīng)用場(chǎng)景

    Golang?context主要用于定義超時(shí)取消,取消后續(xù)操作,在不同操作中傳遞值。本文通過(guò)簡(jiǎn)單易懂的示例進(jìn)行說(shuō)明,感興趣的可以了解一下
    2022-12-12
  • Go語(yǔ)言開(kāi)發(fā)kube-scheduler整體架構(gòu)深度剖析

    Go語(yǔ)言開(kāi)發(fā)kube-scheduler整體架構(gòu)深度剖析

    這篇文章主要為大家介紹了Go語(yǔ)言開(kāi)發(fā)kube-scheduler整體架構(gòu)深度剖析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-04-04
  • GoFrame?gredis配置文件及配置方法對(duì)比

    GoFrame?gredis配置文件及配置方法對(duì)比

    這篇文章主要為大家介紹了GoFrame?gredis配置管理中,配置文件及配置方法對(duì)比,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-06-06
  • 深入了解Golang為什么需要超時(shí)控制

    深入了解Golang為什么需要超時(shí)控制

    本文將介紹為什么需要超時(shí)控制,然后詳細(xì)介紹Go語(yǔ)言中實(shí)現(xiàn)超時(shí)控制的方法,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起了解一下
    2023-05-05
  • golang執(zhí)行命令操作 exec.Command

    golang執(zhí)行命令操作 exec.Command

    這篇文章主要介紹了golang執(zhí)行命令操作 exec.Command,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2020-12-12
  • go語(yǔ)言中for?range使用方法及避坑指南

    go語(yǔ)言中for?range使用方法及避坑指南

    Go中的for range組合可以和方便的實(shí)現(xiàn)對(duì)一個(gè)數(shù)組或切片進(jìn)行遍歷,但是在某些情況下使用for range時(shí)很可能就會(huì)被"坑",下面這篇文章主要給大家介紹了關(guān)于go語(yǔ)言中for?range使用方法及避坑指南的相關(guān)資料,需要的朋友可以參考下
    2022-09-09
  • VSCode Golang dlv調(diào)試數(shù)據(jù)截?cái)鄦?wèn)題及處理方法

    VSCode Golang dlv調(diào)試數(shù)據(jù)截?cái)鄦?wèn)題及處理方法

    這篇文章主要介紹了VSCode Golang dlv調(diào)試數(shù)據(jù)截?cái)鄦?wèn)題,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-06-06
  • Go??iota?常量基本語(yǔ)法介紹

    Go??iota?常量基本語(yǔ)法介紹

    這篇文章主要介紹了Go?為什么要設(shè)計(jì)?iota?常量,我們介紹了 Go 中 iota 的基本語(yǔ)法。同時(shí)基于歷史資料針對(duì) iota 到底是什么,為什么要這么叫,又有什么用進(jìn)行了一番研究,需要的朋友可以參考下
    2022-06-06
  • Go語(yǔ)言中database/sql的用法介紹

    Go語(yǔ)言中database/sql的用法介紹

    Go語(yǔ)言中的database/sql包定義了對(duì)數(shù)據(jù)庫(kù)的一系列操作,database/sql/driver包定義了應(yīng)被數(shù)據(jù)庫(kù)驅(qū)動(dòng)實(shí)現(xiàn)的接口,這些接口會(huì)被sql包使用,本文將詳細(xì)給大家介紹Go的database/sql的使用方法,需要的朋友可以參考下
    2023-05-05
  • 源碼分析Go語(yǔ)言中g(shù)ofmt實(shí)現(xiàn)原理

    源碼分析Go語(yǔ)言中g(shù)ofmt實(shí)現(xiàn)原理

    gofmt?是?Go?語(yǔ)言官方提供的一個(gè)工具,用于自動(dòng)格式化?Go?源代碼,使其符合?Go?語(yǔ)言的官方編碼風(fēng)格,本文給大家源碼詳細(xì)分析了Go語(yǔ)言中g(shù)ofmt實(shí)現(xiàn)原理,并通過(guò)圖文和代碼講解的非常詳細(xì),需要的朋友可以參考下
    2024-03-03

最新評(píng)論