最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

淺析Go匯編語(yǔ)法和MatrixOne使用介紹

 更新時(shí)間:2022年04月19日 15:23:04   作者:dengn_matrixorigin  
MatrixOne由Go語(yǔ)言所開(kāi)發(fā)是一個(gè)新一代超融合異構(gòu)數(shù)據(jù)庫(kù),致力于打造單一架構(gòu)處理TP、AP、流計(jì)算等多種負(fù)載的極簡(jiǎn)大數(shù)據(jù)引擎,今天通過(guò)本文給大家介紹Go匯編語(yǔ)法和MatrixOne使用,感興趣的朋友一起看看吧

MatrixOne是一個(gè)新一代超融合異構(gòu)數(shù)據(jù)庫(kù),致力于打造單一架構(gòu)處理TP、AP、流計(jì)算等多種負(fù)載的極簡(jiǎn)大數(shù)據(jù)引擎。MatrixOne由Go語(yǔ)言所開(kāi)發(fā),并已于2021年10月開(kāi)源,目前已經(jīng)release到0.3版本。在MatrixOne已發(fā)布的性能報(bào)告中,與業(yè)界領(lǐng)先的OLAP數(shù)據(jù)庫(kù)Clickhouse相比也不落下風(fēng)。作為一款Go語(yǔ)言實(shí)現(xiàn)的數(shù)據(jù)庫(kù),可以達(dá)到C++實(shí)現(xiàn)的數(shù)據(jù)庫(kù)一樣的性能,其中一個(gè)很重要的優(yōu)化就是利用Go語(yǔ)言自帶的匯編能力,來(lái)通過(guò)調(diào)用SIMD指令進(jìn)行硬件加速。本文就將對(duì)Go匯編及在MatrixOne的應(yīng)用做詳細(xì)介紹。

MatrixOne數(shù)據(jù)庫(kù)是什么?

MatrixOne是一個(gè)新一代超融合異構(gòu)數(shù)據(jù)庫(kù),致力于打造單一架構(gòu)處理TP、AP、流計(jì)算等多種負(fù)載的極簡(jiǎn)大數(shù)據(jù)引擎。MatrixOne由Go語(yǔ)言所開(kāi)發(fā),并已于2021年10月開(kāi)源,目前已經(jīng)release到0.3版本。在MatrixOne已發(fā)布的性能報(bào)告中,與業(yè)界領(lǐng)先的OLAP數(shù)據(jù)庫(kù)Clickhouse相比也不落下風(fēng)。作為一款Go語(yǔ)言實(shí)現(xiàn)的數(shù)據(jù)庫(kù),可以達(dá)到C++實(shí)現(xiàn)的數(shù)據(jù)庫(kù)一樣的性能,其中一個(gè)很重要的優(yōu)化就是利用Go語(yǔ)言自帶的匯編能力,來(lái)通過(guò)調(diào)用SIMD指令進(jìn)行硬件加速。本文就將對(duì)Go匯編及在MatrixOne的應(yīng)用做詳細(xì)介紹。

Github地址:https://github.com/matrixorigin/matrixone 有興趣的讀者歡迎star和fork。

Go匯編介紹

Go是一種較新的高級(jí)語(yǔ)言,提供諸如協(xié)程、快速編譯等激動(dòng)人心的特性。但是在數(shù)據(jù)庫(kù)引擎中,使用純粹的Go語(yǔ)言會(huì)有力所未逮的時(shí)候。例如,向量化是數(shù)據(jù)庫(kù)計(jì)算引擎常用的加速手段,而Go語(yǔ)言無(wú)法通過(guò)調(diào)用SIMD指令來(lái)使向量化代碼的性能最大化。又例如,在安全相關(guān)代碼中,Go語(yǔ)言無(wú)法調(diào)用CPU提供的密碼學(xué)相關(guān)指令。在C/C++/Rust的世界中,解決這類(lèi)問(wèn)題可通過(guò)調(diào)用CPU架構(gòu)相關(guān)的intrinsics函數(shù)。而Go語(yǔ)言提供的解決方案是Go匯編。本文將介紹Go匯編的語(yǔ)法特點(diǎn),并通過(guò)幾個(gè)具體場(chǎng)景展示其使用方法。

本文假定讀者已經(jīng)對(duì)計(jì)算機(jī)體系架構(gòu)和匯編語(yǔ)言有基本的了解,因此常用的名詞(比如“寄存器”)不做解釋。如缺乏相關(guān)預(yù)備知識(shí),可以尋求網(wǎng)絡(luò)資源進(jìn)行學(xué)習(xí),例如這里。

如無(wú)特殊說(shuō)明,本文所指的匯編語(yǔ)言皆針對(duì)x86(amd64)架構(gòu)。關(guān)于x86指令集,IntelAMD官方都提供了完整的指令集參考文檔。想快速查閱,也可以使用這個(gè)列表。Intel的intrinsics文檔也可以作為一個(gè)參考。

為什么使用Go匯編?

維基百科把使用匯編語(yǔ)言的理由概括成3類(lèi):

  • 直接操作硬件
  • 使用特殊的CPU指令
  • 解決性能問(wèn)題

Go程序員使用匯編的理由,也不外乎這3類(lèi)。如果你面對(duì)的問(wèn)題在這3個(gè)類(lèi)別里面,并且沒(méi)有現(xiàn)成的庫(kù)可用,就可以考慮使用Go匯編。

為什么不用CGO?

  • 巨大的函數(shù)調(diào)用開(kāi)銷(xiāo)
  • 內(nèi)存管理問(wèn)題
  • 打破goroutine語(yǔ)義 若協(xié)程里運(yùn)行CGO函數(shù),會(huì)占據(jù)單獨(dú)線程,無(wú)法被Go運(yùn)行時(shí)正常調(diào)度。
  • 可移植性差 交叉編譯需要目的平臺(tái)的全套工具鏈。在不同平臺(tái)部署需要安裝更多依賴(lài)庫(kù)。

倘若在你的場(chǎng)景中以上幾點(diǎn)無(wú)法接受,不妨嘗試一下Go匯編。

Go匯編語(yǔ)法特點(diǎn)

根據(jù)Rob Pike的The Design of the Go Assembler,Go使用的匯編語(yǔ)言并不嚴(yán)格與CPU指令一一對(duì)應(yīng),而是一種被稱(chēng)作Plan 9 assembly的“偽匯編”。

The most important thing to know about Go's assembler is that it is not a direct representation of the underlying machine. Some of the details map precisely to the machine, but some do not. This is because the compiler suite needs no assembler pass in the usual pipeline. Instead, the compiler operates on a kind of semi-abstract instruction set, and instruction selection occurs partly after code generation. The assembler works on the semi-abstract form, so when you see an instruction like MOV what the toolchain actually generates for that operation might not be a move instruction at all, perhaps a clear or load. Or it might correspond exactly to the machine instruction with that name. In general, machine-specific operations tend to appear as themselves, while more general concepts like memory move and subroutine call and return are more abstract. The details vary with architecture, and we apologize for the imprecision; the situation is not well-defined.

我們不用關(guān)心Plan 9 assembly與機(jī)器指令的對(duì)應(yīng)關(guān)系,只需要了解Plan 9 assembly的語(yǔ)法特點(diǎn)。網(wǎng)絡(luò)上有一些可獲得的文檔,如這里這里。

一例勝千言,下面我們以最簡(jiǎn)單的64位整數(shù)加法為例,從不同方面來(lái)看Go匯編語(yǔ)法的特點(diǎn)。

// add.go
func Add(x, y int64) int64
//add_amd64.s
#include "textflag.h"
TEXT ·Add(SB), NOSPLIT, $0-24
	MOVQ x+0(FP), AX
	MOVQ y+8(FP), CX
    ADDQ AX, CX
    MOVQ CX, ret+16(FP)
	RET

這四條匯編代碼所做的依次是:

  • 第一個(gè)操作數(shù)x放入寄存器AX
  • 第二個(gè)操作數(shù)y放入寄存器
  • CXCX加上AX,結(jié)果放回CX
  • CX放入返回值所在棧地址

操作數(shù)順序

x86匯編最常用的語(yǔ)法有兩種,AT&T語(yǔ)法和Intel語(yǔ)法。AT&T語(yǔ)法結(jié)果數(shù)放在最后,其他操作數(shù)放在前面。Intel語(yǔ)法結(jié)果數(shù)放最前面,其他操作數(shù)在后面。

Go的匯編在這方面接近AT&T語(yǔ)法,結(jié)果數(shù)放最后。

一個(gè)容易寫(xiě)錯(cuò)的例子是CMP指令。從效果上來(lái)看,CMP類(lèi)似于SUB指令只修改EFLAGS標(biāo)志位,不修改操作數(shù)。而在Go匯編中,CMP是以第一個(gè)操作數(shù)減去第二個(gè)操作數(shù)(與SUB相反)的結(jié)果來(lái)設(shè)置標(biāo)志位。

寄存器寬度標(biāo)識(shí)

部分指令支持不同的寄存器寬度。以64位操作數(shù)的ADD為例,按AT&T語(yǔ)法,指令名要加上寬度后綴變成ADDQ,寄存器也要加上寬度前綴變成RAX和RCX。按Intel語(yǔ)法,指令名不變,只給寄存器加上前綴。

上面例子可以看出,Go匯編跟兩者都不同:指令名需要加寬度后綴,寄存器不變。

函數(shù)調(diào)用約定

編程語(yǔ)言在函數(shù)調(diào)用中傳遞參數(shù)的方式,稱(chēng)做函數(shù)調(diào)用約定(function calling convention)。x86-64架構(gòu)上的主流C/C++編譯器,都默認(rèn)使用基于寄存器的方式:調(diào)用者把參數(shù)放進(jìn)特定的寄存器傳給被調(diào)用函數(shù)。而Go的調(diào)用約定,簡(jiǎn)單地講,在最新的Go 1.18上,Go自己的runtime庫(kù)在amd64與arm64與ppc64架構(gòu)上使用基于寄存器的方式,其余地方(其他的CPU架構(gòu),以及非runtime庫(kù)和用戶(hù)寫(xiě)的庫(kù))使用基于棧的方式:調(diào)用者把參數(shù)依次壓棧,被調(diào)用者通過(guò)傳遞的偏移量去棧中訪問(wèn),執(zhí)行結(jié)束后再把返回值壓棧。

在上面代碼中,F(xiàn)P是一個(gè)虛擬寄存器,指向第一個(gè)參數(shù)在棧中的地址。多個(gè)參數(shù)和返回值會(huì)按順序?qū)R存放,因此x,y,返回值在棧中地址分別是FP加上偏移量0,8,16。

對(duì)寫(xiě)Go匯編代碼有幫助的工具

avo

熟悉匯編語(yǔ)言的讀者應(yīng)該知道,手寫(xiě)匯編語(yǔ)言,會(huì)有選擇寄存器、計(jì)算偏移量等繁瑣且易出錯(cuò)的步驟。avo庫(kù)就是為解決此類(lèi)問(wèn)題而生。如欲了解avo的具體用法,請(qǐng)參見(jiàn)其repo中給出的樣例

text/template

這是Go語(yǔ)言自帶的一個(gè)庫(kù)。在寫(xiě)大量重復(fù)代碼時(shí)會(huì)有幫助,例如在向量化代碼中為不同類(lèi)型實(shí)現(xiàn)相同基本算子。具體用法參見(jiàn)官方文檔,這里不占用篇幅。

在Go匯編代碼中使用宏

Go匯編代碼支持跟C語(yǔ)言類(lèi)似的宏,也可以用在代碼大量重復(fù)的場(chǎng)景。內(nèi)部庫(kù)中就有很多例子,比如這里。

在MatrixOne數(shù)據(jù)庫(kù)中的Go語(yǔ)言匯編應(yīng)用

基本向量運(yùn)算加速

在OLAP數(shù)據(jù)庫(kù)計(jì)算引擎中,向量化是必不可少的加速手段。通過(guò)向量化,消除了大量簡(jiǎn)單函數(shù)調(diào)用帶來(lái)的不必要開(kāi)銷(xiāo)。而為了達(dá)到最大的向量化性能,使用SIMD指令是十分自然的選擇。

我們以8位整數(shù)向量化加法為例。將兩個(gè)數(shù)組的元素兩兩相加,把結(jié)果放入第三個(gè)數(shù)組。這樣的操作在某些C/C++編譯器中,可以自動(dòng)優(yōu)化成使用SIMD指令的版本。而以編譯速度見(jiàn)長(zhǎng)的Go編譯器,不會(huì)做這樣的優(yōu)化。這也是Go語(yǔ)言為了保證編譯速度所做的主動(dòng)選擇。在這個(gè)例子中,我們介紹如何使用Go匯編以AVX2指令集實(shí)現(xiàn)int8類(lèi)型向量加法(假設(shè)數(shù)組已經(jīng)按32字節(jié)填充)。

由于AVX2一共有16個(gè)256位寄存器,我們希望在循環(huán)展開(kāi)中把它們?nèi)渴褂蒙稀H绻耆謱?xiě)的話,重復(fù)羅列寄存器非常繁瑣且容易出錯(cuò)。因此我們使用avo來(lái)簡(jiǎn)化一些工作。avo的向量加法代碼如下:

package main

import (
	. "github.com/mmcloughlin/avo/build"
	. "github.com/mmcloughlin/avo/operand"
	. "github.com/mmcloughlin/avo/reg"
)
var unroll = 16
var regWidth = 32
func main() {
    TEXT("int8AddAvx2Asm", NOSPLIT, "func(x []int8, y []int8, r []int8)")
    x := Mem{Base: Load(Param("x").Base(), GP64())}
    y := Mem{Base: Load(Param("y").Base(), GP64())}
    r := Mem{Base: Load(Param("r").Base(), GP64())}
    n := Load(Param("x").Len(), GP64())
    blocksize := regWidth * unroll
    blockitems := blocksize / 1
    regitems := regWidth / 1
    Label("int8AddBlockLoop")
    CMPQ(n, U32(blockitems))
    JL(LabelRef("int8AddTailLoop"))
    xs := make([]VecVirtual, unroll)
    for i := 0; i < unroll; i++ {
        xs[i] = YMM()
        VMOVDQU(x.Offset(regWidth*i), xs[i])
    }
        VPADDB(y.Offset(regWidth*i), xs[i], xs[i])
        VMOVDQU(xs[i], r.Offset(regWidth*i))
    ADDQ(U32(blocksize), x.Base)
    ADDQ(U32(blocksize), y.Base)
    ADDQ(U32(blocksize), r.Base)
    SUBQ(U32(blockitems), n)
    JMP(LabelRef("int8AddBlockLoop"))
    Label("int8AddTailLoop")
    CMPQ(n, U32(regitems))
    JL(LabelRef("int8AddDone"))
    VMOVDQU(x, xs[0])
    VPADDB(y, xs[0], xs[0])
    VMOVDQU(xs[0], r)
    ADDQ(U32(regWidth), x.Base)
    ADDQ(U32(regWidth), y.Base)
    ADDQ(U32(regWidth), r.Base)
    SUBQ(U32(regitems), n)
    JMP(LabelRef("int8AddTailLoop"))
    Label("int8AddDone")
    RET()
}

運(yùn)行命令

go run int8add.go -out int8add.s

之后生成的匯編代碼如下:

// Code generated by command: go run int8add.go -out int8add.s. DO NOT EDIT.

#include "textflag.h"
// func int8AddAvx2Asm(x []int8, y []int8, r []int8)
// Requires: AVX, AVX2
TEXT ·int8AddAvx2Asm(SB), NOSPLIT, $0-72
	MOVQ x_base+0(FP), AX
	MOVQ y_base+24(FP), CX
	MOVQ r_base+48(FP), DX
	MOVQ x_len+8(FP), BX
int8AddBlockLoop:
	CMPQ    BX, $0x00000200
	JL      int8AddTailLoop
	VMOVDQU (AX), Y0
	VMOVDQU 32(AX), Y1
	VMOVDQU 64(AX), Y2
	VMOVDQU 96(AX), Y3
	VMOVDQU 128(AX), Y4
	VMOVDQU 160(AX), Y5
	VMOVDQU 192(AX), Y6
	VMOVDQU 224(AX), Y7
	VMOVDQU 256(AX), Y8
	VMOVDQU 288(AX), Y9
	VMOVDQU 320(AX), Y10
	VMOVDQU 352(AX), Y11
	VMOVDQU 384(AX), Y12
	VMOVDQU 416(AX), Y13
	VMOVDQU 448(AX), Y14
	VMOVDQU 480(AX), Y15
	VPADDB  (CX), Y0, Y0
	VPADDB  32(CX), Y1, Y1
	VPADDB  64(CX), Y2, Y2
	VPADDB  96(CX), Y3, Y3
	VPADDB  128(CX), Y4, Y4
	VPADDB  160(CX), Y5, Y5
	VPADDB  192(CX), Y6, Y6
	VPADDB  224(CX), Y7, Y7
	VPADDB  256(CX), Y8, Y8
	VPADDB  288(CX), Y9, Y9
	VPADDB  320(CX), Y10, Y10
	VPADDB  352(CX), Y11, Y11
	VPADDB  384(CX), Y12, Y12
	VPADDB  416(CX), Y13, Y13
	VPADDB  448(CX), Y14, Y14
	VPADDB  480(CX), Y15, Y15
	VMOVDQU Y0, (DX)
	VMOVDQU Y1, 32(DX)
	VMOVDQU Y2, 64(DX)
	VMOVDQU Y3, 96(DX)
	VMOVDQU Y4, 128(DX)
	VMOVDQU Y5, 160(DX)
	VMOVDQU Y6, 192(DX)
	VMOVDQU Y7, 224(DX)
	VMOVDQU Y8, 256(DX)
	VMOVDQU Y9, 288(DX)
	VMOVDQU Y10, 320(DX)
	VMOVDQU Y11, 352(DX)
	VMOVDQU Y12, 384(DX)
	VMOVDQU Y13, 416(DX)
	VMOVDQU Y14, 448(DX)
	VMOVDQU Y15, 480(DX)
	ADDQ    $0x00000200, AX
	ADDQ    $0x00000200, CX
	ADDQ    $0x00000200, DX
	SUBQ    $0x00000200, BX
	JMP     int8AddBlockLoop
int8AddTailLoop:
	CMPQ    BX, $0x00000020
	JL      int8AddDone
	ADDQ    $0x00000020, AX
	ADDQ    $0x00000020, CX
	ADDQ    $0x00000020, DX
	SUBQ    $0x00000020, BX
	JMP     int8AddTailLoop
int8AddDone:
	RET

可以看到,在avo代碼中,我們只需要給變量指定寄存器類(lèi)型,生成匯編的時(shí)候會(huì)自動(dòng)幫我們綁定相應(yīng)類(lèi)型的可用寄存器。在很多場(chǎng)景下這確實(shí)能夠帶來(lái)方便。不過(guò)avo目前只支持x86架構(gòu),給arm CPU寫(xiě)匯編無(wú)法使用。

Go語(yǔ)言無(wú)法直接調(diào)用的指令

除了SIMD,還有很多Go語(yǔ)言本身無(wú)法使用到的CPU指令,比如密碼學(xué)相關(guān)指令。如果是用C/C++,可以使用編譯器內(nèi)置的intrinsics函數(shù)(gcc和clang皆提供)來(lái)調(diào)用,還算方便。遺憾的是Go語(yǔ)言并不提供intrinsics函數(shù)。遇到這樣的場(chǎng)景,匯編是唯一的解決辦法。Go語(yǔ)言自己的crypto官方庫(kù)里就有大量的匯編代碼。

這里我們以CRC32C指令作為例子。在MatrixOne的哈希表實(shí)現(xiàn)中,整數(shù)key的哈希函數(shù)只使用一條CRC32指令,達(dá)到了理論上的最高性能。代碼如下:

TEXT ·Crc32Int64Hash(SB), NOSPLIT, $0-16
	MOVQ   -1, SI
	CRC32Q data+0(FP), SI
	MOVQ   SI, ret+8(FP)
	RET

實(shí)際代碼中,為了消除匯編函數(shù)調(diào)用帶來(lái)的指令跳轉(zhuǎn)開(kāi)銷(xiāo),以及參數(shù)進(jìn)出棧開(kāi)銷(xiāo),使用的是批量化的版本。這里為了節(jié)約篇幅,我們用簡(jiǎn)化版舉例。

編譯器無(wú)法達(dá)到的特殊優(yōu)化效果

下面是MatrixOne使用的兩個(gè)有序64位整數(shù)數(shù)組求交集的算法的一部分:

...
loop:
	CMPQ  DX, DI
	JE    done
	CMPQ  R11, R8
	JE    done
	MOVQ  (DX), R10
	MOVQ  R10, (SI)
	CMPQ  R10, (R11)
	SETLE AL
	SETGE BL
	SETEQ CL
	SHLB  $0x03, AL
	SHLB  $0x03, BL
	SHLB  $0x03, CL
	ADDQ  AX, DX
	ADDQ  BX, R11
	ADDQ  CX, SI
	JMP   loop

done:
...

CMPQ R10, (R11)這一行,是比較兩個(gè)數(shù)組當(dāng)前指針位置的元素。后面幾行根據(jù)這個(gè)比較的結(jié)果,來(lái)移動(dòng)對(duì)應(yīng)操作數(shù)數(shù)組及結(jié)果數(shù)組的指針。文字解釋不如對(duì)比下面等價(jià)的C語(yǔ)言代碼來(lái)得清楚:

while (true) {
    if (a == a_end) break;
    if (b == b_end) break;
    *c = *a;
    if (*a <= *b) ++a;
    if (*a >= *b) ++b;
    if (*a == *b) ++c;
}

匯編代碼中,循環(huán)體內(nèi)只做了一次比較運(yùn)算,并且沒(méi)有任何的分支跳轉(zhuǎn)。高級(jí)語(yǔ)言編譯器達(dá)不到這樣的優(yōu)化效果,原因是任何高級(jí)語(yǔ)言都不提供“根據(jù)一個(gè)比較運(yùn)算的3種不同結(jié)果,分別修改3個(gè)不同的數(shù)”這樣直接跟CPU指令集相關(guān)的語(yǔ)義。

這個(gè)例子算是對(duì)匯編語(yǔ)言威力的一個(gè)展示。編程語(yǔ)言不斷發(fā)展,抽象層次越來(lái)越高,但是在性能最大化的場(chǎng)景下,仍然需要直接與CPU指令打交道的匯編語(yǔ)言。

到此這篇關(guān)于淺析Go匯編語(yǔ)法和MatrixOne使用介紹的文章就介紹到這了,更多相關(guān)Go匯編MatrixOne使用內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Golang實(shí)現(xiàn)簡(jiǎn)易的命令行功能

    Golang實(shí)現(xiàn)簡(jiǎn)易的命令行功能

    這篇文章主要為大家詳細(xì)介紹了如何通過(guò)Golang實(shí)現(xiàn)一個(gè)簡(jiǎn)易的命令行功能,文中的示例代碼講解詳細(xì),具有一定的學(xué)習(xí)價(jià)值,感興趣的可以了解一下
    2023-02-02
  • go?test?命令示例詳解

    go?test?命令示例詳解

    go?test是Go用來(lái)執(zhí)行測(cè)試函數(shù)(test?function)、基準(zhǔn)函數(shù)(benchmark?function)和示例函數(shù)(example?function)的命令,這篇文章主要介紹了go?test?命令,需要的朋友可以參考下
    2023-11-11
  • 重學(xué)Go語(yǔ)言之如何開(kāi)發(fā)RPC應(yīng)用

    重學(xué)Go語(yǔ)言之如何開(kāi)發(fā)RPC應(yīng)用

    這篇文章主要為大家詳細(xì)介紹了在Go語(yǔ)言中如何構(gòu)建RPC應(yīng)用,文中的示例代碼講解詳細(xì),具有一定的學(xué)習(xí)價(jià)值,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2023-09-09
  • golang的協(xié)程上下文的具體使用

    golang的協(xié)程上下文的具體使用

    golang的context?主要用來(lái)在?goroutine?之間傳遞上下文信息,包括:取消信號(hào)、超時(shí)時(shí)間、截止時(shí)間、k-v?等,本文就詳細(xì)的來(lái)介紹一下golang的協(xié)程上下文的具體使用,感興趣的可以了解一下
    2022-04-04
  • Go語(yǔ)言展現(xiàn)快速排序算法全過(guò)程的思路及代碼示例

    Go語(yǔ)言展現(xiàn)快速排序算法全過(guò)程的思路及代碼示例

    這篇文章主要介紹了Go語(yǔ)言展現(xiàn)快速排序算法全過(guò)程的思路及代碼示例,文章最后作者還提到了對(duì)Quick Sort算法優(yōu)化的一些想法,需要的朋友可以參考下
    2016-04-04
  • golang代碼檢測(cè)工具之goimports解讀

    golang代碼檢測(cè)工具之goimports解讀

    這篇文章主要介紹了golang代碼檢測(cè)工具之goimports使用,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-01-01
  • Go映射的使用

    Go映射的使用

    Go提供了另一個(gè)重要的數(shù)據(jù)類(lèi)型,稱(chēng)為map,它將唯一鍵映射到值,本文主要介紹了Go映射的使用,包括聲明映射、初始化映射、操作映射等,感興趣的可以了解一下
    2023-11-11
  • Golang中這些channel用法你了解嗎

    Golang中這些channel用法你了解嗎

    channel?是GO語(yǔ)言中一種特殊的類(lèi)型,是連接并發(fā)goroutine的管道,這篇文章主要來(lái)和大家分享一下關(guān)于?nil?channel?通道,有緩沖通道,無(wú)緩沖通道的常用方法以及巧妙使用的方式,希望對(duì)大家有所幫助
    2023-08-08
  • Go實(shí)現(xiàn)socks5服務(wù)器的方法

    Go實(shí)現(xiàn)socks5服務(wù)器的方法

    SOCKS5 是一個(gè)代理協(xié)議,它在使用TCP/IP協(xié)議通訊的前端機(jī)器和服務(wù)器機(jī)器之間扮演一個(gè)中介角色,使得內(nèi)部網(wǎng)中的前端機(jī)器變得能夠訪問(wèn)Internet網(wǎng)中的服務(wù)器,或者使通訊更加安全,這篇文章主要介紹了Go實(shí)現(xiàn)socks5服務(wù)器的方法,需要的朋友可以參考下
    2023-07-07
  • Golang使用channel實(shí)現(xiàn)一個(gè)優(yōu)雅退出功能

    Golang使用channel實(shí)現(xiàn)一個(gè)優(yōu)雅退出功能

    最近補(bǔ)?Golang?channel?方面八股的時(shí)候發(fā)現(xiàn)用?channel?實(shí)現(xiàn)一個(gè)優(yōu)雅退出功能好像不是很難,之前寫(xiě)的?HTTP?框架剛好也不支持優(yōu)雅退出功能,于是就參考了?Hertz?優(yōu)雅退出方面的代碼,為我的?PIANO?補(bǔ)足了這個(gè)?feature
    2023-03-03

最新評(píng)論

池州市| 乐东| 萝北县| 嘉峪关市| 沈丘县| 伊川县| 岳阳市| 彭阳县| 兴和县| 巴彦淖尔市| 长岛县| 沂源县| 五常市| 高尔夫| 石阡县| 常熟市| 罗城| 墨竹工卡县| 循化| 斗六市| 团风县| 忻城县| 灌云县| 汉中市| 东山县| 甘德县| 浦东新区| 花莲市| 五河县| 砀山县| 稷山县| 齐河县| 高平市| 上犹县| 贵南县| 拜泉县| 周宁县| 雅江县| 久治县| 鄂托克旗| 来凤县|