深入探究Golang中flag標(biāo)準(zhǔn)庫的使用
在使用 Go 進(jìn)行開發(fā)的過程中,命令行參數(shù)解析是我們經(jīng)常遇到的需求。而 flag 包正是一個(gè)用于實(shí)現(xiàn)命令行參數(shù)解析的 Go 標(biāo)準(zhǔn)庫。在本文中,我們將深入探討 flag 標(biāo)準(zhǔn)庫的實(shí)現(xiàn)原理和使用技巧,以幫助讀者更好地理解和掌握該庫的使用方法。
1.使用
1.1示例
flag 基本使用示例代碼如下:
package main
import (
"flag"
"fmt"
)
type flagVal struct {
val string
}
func (v *flagVal) String() string {
return v.val
}
func (v *flagVal) Set(s string) error {
v.val = s
return nil
}
func main() {
// 1. 使用 flag.Type() 返回 *int 類型命令行參數(shù)
var nFlag = flag.Int("n", 1234, "help message for flag n")
// 2. 使用 flag.TypeVar() 綁定命令行參數(shù)到 int 類型變量
var flagvar int
flag.IntVar(&flagvar, "flagvar", 1234, "help message for flagvar")
// 3. 使用 flag.Var() 綁定命令行參數(shù)到實(shí)現(xiàn)了 flag.Value 接口的自定義類型變量
val := flagVal{}
flag.Var(&val, "val", "help message for val")
// 解析命令行參數(shù)
flag.Parse()
fmt.Printf("nFlag: %d\n", *nFlag)
fmt.Printf("flagvar: %d\n", flagvar)
fmt.Printf("val: %+v\n", val)
fmt.Printf("NFlag: %v\n", flag.NFlag()) // 返回已設(shè)置的命令行標(biāo)志個(gè)數(shù)
fmt.Printf("NArg: %v\n", flag.NArg()) // 返回處理完標(biāo)志后剩余的參數(shù)個(gè)數(shù)
fmt.Printf("Args: %v\n", flag.Args()) // 返回處理完標(biāo)志后剩余的參數(shù)列表
fmt.Printf("Arg(1): %v\n", flag.Arg(1)) // 返回處理完標(biāo)志后剩余的參數(shù)列表中第 i 項(xiàng)
}可以通過指定 --help/-h 參數(shù)來查看這個(gè)命令行程序的使用幫助:
$ go run main.go -h
Usage of ./main:
-flagvar int
help message for flagvar (default 1234)
-n int
help message for flag n (default 1234)
-val value
help message for val
這個(gè)程序接收三個(gè)命令行參數(shù):
int類型的-flagvar,默認(rèn)值為2134。int類型的-n,默認(rèn)值為2134。value類型的-val,無默認(rèn)值。
我們可以將 -flagvar、-n、-val 稱作 flag,即「標(biāo)志」,這也是 Go 內(nèi)置命令行參數(shù)解析庫被命名為 flag 的原因,見名知意。
這三個(gè)參數(shù)在示例代碼中,分別使用了三種不同形式來指定:
flag.Type():
-n 標(biāo)志是使用 var nFlag = flag.Int("n", 1234, "help message for flag n") 來指定的。
flag.Int 函數(shù)簽名如下:
func Int(name string, value int, usage string) *int
flag.Int 函數(shù)接收三個(gè)參數(shù),分別是標(biāo)志名稱、標(biāo)志默認(rèn)參數(shù)值、標(biāo)志使用幫助信息。函數(shù)最終還會(huì)返回一個(gè) *int 類型的值,表示用戶在執(zhí)行命令行程序時(shí)為這個(gè)標(biāo)志指定的參數(shù)。
除了使用 flag.Int 來設(shè)置 int 類型標(biāo)志,flag 還支持其他多種類型,如使用 flag.String 來設(shè)置 string 類型標(biāo)志。
flag.TypeVar():
-flagvar 標(biāo)志是使用 flag.IntVar(&flagvar, "flagvar", 1234, "help message for flagvar") 來指定的。
flag.IntVar 函數(shù)簽名如下:
func IntVar(p *int, name string, value int, usage string)
與 flag.Int 不同的是,flag.IntVar 函數(shù)取消了返回值,而是會(huì)將用戶傳遞的命令行參數(shù)綁定到第一個(gè)參數(shù) p *int。
除了使用 flag.IntVar 來綁定 int 類型參數(shù)到標(biāo)志,flag 還提供其他多個(gè)函數(shù)來支持綁定不同類型參數(shù)到標(biāo)志,如使用 flag.StringVar 來綁定 string 類型標(biāo)志。
flag.Var():
-val 標(biāo)志是使用 flag.Var(&val, "val", "help message for val") 來指定的。
flag.Var 函數(shù)簽名如下:
func Var(value Value, name string, usage string)
flag.Var 函數(shù)接收三個(gè)參數(shù),后兩個(gè)參數(shù)分別是標(biāo)志名稱、標(biāo)志使用幫助信息。而用戶傳遞的命令行參數(shù)將被綁定到第一個(gè)參數(shù) value。
type Value interface {
String() string
Set(string) error
}我們可以自定義類型,只要實(shí)現(xiàn)了 flag.Value 接口,都可以傳遞給 flag.Var,這極大的增加了 flag 包的靈活性。
定義完三個(gè)標(biāo)志,我們還需要使用 flag.Parse() 來解析命令行參數(shù),只有解析成功以后,才會(huì)將戶傳遞的命令行參數(shù)值綁定到對(duì)應(yīng)的標(biāo)志變量中。之后就可以使用 nFlag、flagvar、val 的變量值了。
在 main 函數(shù)底部,使用 flag.NFlag()、flag.NArg()、flag.Args()、flag.Arg(1) 幾個(gè)函數(shù)獲取并展示了命令行參數(shù)相關(guān)信息。
現(xiàn)在我們嘗試給這個(gè)命令行程序傳遞幾個(gè)參數(shù)并執(zhí)行它,看下輸出結(jié)果:
$ go run main.go -n 100 -val test a b c d
nFlag: 100
flagvar: 1234
val: {val:test}
NFlag: 2
NArg: 4
Args: [a b c d]
Arg(1): b
我們通過 -n 100 為 -n 標(biāo)志指定了參數(shù)值 100,最終會(huì)被賦值給 nFlag 變量。
由于沒有指定 flagvar 標(biāo)志的參數(shù)值,所以 flagvar 變量會(huì)被賦予默認(rèn)值 1234。
接著,我們又通過 -val test 為 -val 標(biāo)志指定了參數(shù)值 test,最終賦值給了自定義的 flagVal 結(jié)構(gòu)體的 val 字段。
因?yàn)橹辉O(shè)置了 -n 和 -val 兩個(gè)標(biāo)志的參數(shù)值,所以函數(shù) flag.NFlag() 返回結(jié)果為 2。
a b c d 四個(gè)參數(shù)由于沒有被定義,所以 flag.NArg() 返回結(jié)果為 4。
flag.Args() 返回的切片中存儲(chǔ)了 a b c d 四個(gè)參數(shù)。
flag.Arg(1) 返回切片中下標(biāo)為 1 位置的參數(shù),即 b。
1.2標(biāo)志類型
在上面的示例中,我們展示了 int 類型和自定義的 flag.Value 的使用,flag 包支持的所有標(biāo)志類型匯總?cè)缦拢?/p>
| 參數(shù)類型 | 合法值 |
|---|---|
| bool | strconv.ParseBool 能夠解析的有效值,接受:1, 0, t, f, T, F, true, false, TRUE, FALSE, True, False。 |
| time.Duration | time.ParseDuration 能夠解析的有效值,如:”300ms”, “-1.5h” or “2h45m”,合法單位:”ns”, “us” (or “µs”), “ms”, “s”, “m”, “h”。 |
| float64 | 合法的浮點(diǎn)數(shù)類型。 |
| int/int64/uint/uint64 | 合法的整數(shù)類型,如:1234, 0664, 0x1234,也可以是負(fù)數(shù)。 |
| string | 合法的字符串類型。 |
| flag.Value | 實(shí)現(xiàn)了該接口的類型。 |
除了支持幾種 Go 默認(rèn)的原生類型外,如果我們想實(shí)現(xiàn)其他類型標(biāo)志的定義,都可以通過 flag.Value 接口類型來完成。其實(shí) flag 包內(nèi)部對(duì)于 bool、int 等所有類型的定義,都實(shí)現(xiàn)了 flag.Value 接口,在稍后講解源碼過程中將會(huì)有所體現(xiàn)。
1.3標(biāo)志語法
命令行標(biāo)志支持多種語法:
| 語法 | 說明 |
|---|---|
| -flag | bool 類型標(biāo)志可以使用,表示參數(shù)值為 true。 |
| –flag | 支持兩個(gè) - 字符,與 -flag 等價(jià)。 |
| -flag=x | 所有類型通用,為標(biāo)志 flag 傳遞參數(shù)值 x。 |
| -flag x | 作用等價(jià)于 -flag=x,但是僅限非 bool 類型標(biāo)志使用,假如這樣使用 cmd -x *,其中 * 是 Unix shell 通配符,如果存在名為 0、false 等文件,則參數(shù)值結(jié)果會(huì)發(fā)生變化。 |
flag 解析參數(shù)時(shí)會(huì)在第一個(gè)非標(biāo)志參數(shù)之前(單獨(dú)的一個(gè) - 字符也是非標(biāo)志參數(shù))或終止符 -- 之后停止。
2.源碼解讀
注意:本文以 Go 1.19.4 源碼為例,其他版本可能存在差異。
熟悉了 flag 包的基本使用,接下來我們就要深入到 flag 的源碼,來探究其內(nèi)部是如何實(shí)現(xiàn)。
閱讀 flag 包的源碼,我們可以從使用 flag 包的流程來入手。
2.1定義標(biāo)志
在 main 函數(shù)中,我們首先通過如下代碼定義了一個(gè)標(biāo)志 -n。
var nFlag = flag.Int("n", 1234, "help message for flag n")flag.Int 函數(shù)定義如下:
func Int(name string, value int, usage string) *int {
return CommandLine.Int(name, value, usage)
}可以發(fā)現(xiàn),flag.Int 函數(shù)調(diào)用并返回了 CommandLine 對(duì)象的 Int 方法,并將參數(shù)原樣傳遞進(jìn)去。
來看看 CommandLine 是個(gè)什么:
var CommandLine = NewFlagSet(os.Args[0], ExitOnError)
func NewFlagSet(name string, errorHandling ErrorHandling) *FlagSet {
f := &FlagSet{
name: name,
errorHandling: errorHandling,
}
f.Usage = f.defaultUsage
return f
}CommandLine 是使用 NewFlagSet 創(chuàng)建的 FlagSet 結(jié)構(gòu)體指針,在構(gòu)造 FlagSet 對(duì)象時(shí),需要兩個(gè)參數(shù) os.Args[0] 和 ExitOnError。
我們知道 os.Args 存儲(chǔ)了程序執(zhí)行時(shí)指定的所有命令行參數(shù),os.Args[0] 就是當(dāng)前命令行程序的名稱,ExitOnError 是一個(gè)常量,用來標(biāo)記在出現(xiàn) error 時(shí)應(yīng)該如何做,ExitOnError 表示在遇到 error 時(shí)退出程序。
來看下 FlagSet 是如何定義:
type FlagSet struct {
Usage func()
name string
parsed bool
actual map[string]*Flag
formal map[string]*Flag
args []string // arguments after flags
errorHandling ErrorHandling
output io.Writer // nil means stderr; use Output() accessor
}Usage 字段是一個(gè)函數(shù),根據(jù)名字大概能夠猜測出,這個(gè)函數(shù)會(huì)在指定 --help/-h 參數(shù)查看命令行程序使用幫助時(shí)被調(diào)用。
parsed 用來標(biāo)記是否調(diào)用過 flag.Parse()。
actual 和 formal 分別用來存儲(chǔ)從命令行解析的標(biāo)志參數(shù)和在程序中指定的默認(rèn)標(biāo)志參數(shù)。它們都使用 map 來存儲(chǔ) Flag 類型的指針,FlagSet 可以看作是 Flag 結(jié)構(gòu)體的「集合」。
args 用來保存處理完標(biāo)志后剩余的參數(shù)列表。
errorHandling 標(biāo)記在出現(xiàn) error 時(shí)應(yīng)該如何做。
output 用來設(shè)置輸出位置,這可以改變 --help/-h 時(shí)展示幫助信息的輸出位置。
現(xiàn)在來看下 Flag 的定義:
type Flag struct {
Name string // 標(biāo)志名稱
Usage string // 幫助信息
Value Value // 標(biāo)志所對(duì)應(yīng)的命令行參數(shù)值
DefValue string // 用來記錄字符串類型的默認(rèn)值,它不會(huì)被改變
}Flag 用來記錄一個(gè)命令行參數(shù),里面存儲(chǔ)了一個(gè)標(biāo)志所有信息。
可以說 Flag 和 FlagSet 兩個(gè)結(jié)構(gòu)體就是 flag 包的核心,所有功能都是圍繞這兩個(gè)結(jié)構(gòu)體設(shè)計(jì)的。
標(biāo)志所對(duì)應(yīng)的命令行參數(shù)值為 flag.Value 接口類型,在前文中已經(jīng)見過了,定義如下:
type Value interface {
String() string
Set(string) error
}之所以使用接口,是為了能夠存儲(chǔ)任何類型的值,除了 flag 包默認(rèn)支持的內(nèi)置類型,用戶也可以定義自己的類型,只要實(shí)現(xiàn)了 Value 接口即可。
如我們在前文示例程序中定義的 flagVal 類型。
現(xiàn)在 CommandLine 的定義以及內(nèi)部實(shí)現(xiàn)我們都看過了,是時(shí)候回過頭來看一看 CommandLine 對(duì)象的 Int 方法了:
func (f *FlagSet) Int(name string, value int, usage string) *int {
p := new(int)
f.IntVar(p, name, value, usage)
return p
}Int 方法內(nèi)部調(diào)用了 f.IntVar() 方法,定義如下:
func (f *FlagSet) IntVar(p *int, name string, value int, usage string) {
f.Var(newIntValue(value, p), name, usage)
}IntVar 方法又調(diào)用了 f.Var() 方法。
Var 方法第一個(gè)參數(shù)為 newIntValue(value, p),我們來看看 newIntValue 函數(shù)是如何定義的:
type intValue int
func newIntValue(val int, p *int) *intValue {
*p = val
return (*intValue)(p)
}
func (i *intValue) Set(s string) error {
v, err := strconv.ParseInt(s, 0, strconv.IntSize)
if err != nil {
err = numError(err)
}
*i = intValue(v)
return err
}
func (i *intValue) Get() any { return int(*i) }
func (i *intValue) String() string { return strconv.Itoa(int(*i)) }newIntValue 是一個(gè)構(gòu)造函數(shù),用來創(chuàng)建一個(gè) intValue 類型的指針,intValue 底層類型實(shí)際上是 int。
定義 intValue 類型的目的就是為了實(shí)現(xiàn) flag.Value 接口。
再來看下 Var 方法如何定義:
func (f *FlagSet) Var(value Value, name string, usage string) {
// Flag must not begin "-" or contain "=".
if strings.HasPrefix(name, "-") {
panic(f.sprintf("flag %q begins with -", name))
} else if strings.Contains(name, "=") {
panic(f.sprintf("flag %q contains =", name))
}
// Remember the default value as a string; it won't change.
flag := &Flag{name, usage, value, value.String()}
_, alreadythere := f.formal[name]
if alreadythere {
var msg string
if f.name == "" {
msg = f.sprintf("flag redefined: %s", name)
} else {
msg = f.sprintf("%s flag redefined: %s", f.name, name)
}
panic(msg) // Happens only if flags are declared with identical names
}
if f.formal == nil {
f.formal = make(map[string]*Flag)
}
f.formal[name] = flag
}name 參數(shù)即為標(biāo)志名,在 Var 方法內(nèi)部,首先對(duì)標(biāo)志名的合法性進(jìn)行了校驗(yàn),不能以 - 開頭且不包含 =。
接著,根據(jù)參數(shù)創(chuàng)建了一個(gè) Flag 類型,并且校驗(yàn)了標(biāo)志是否被重復(fù)定義。
最后將 Flag 保存在 formal 屬性中。
到這里,整個(gè)函數(shù)調(diào)用關(guān)系就結(jié)束了,我們來梳理一下代碼執(zhí)行流程:
flag.Int -> CommandLine.Int -> CommandLine.IntVar -> CommandLine.Var。
經(jīng)過這個(gè)調(diào)用過程,我們就得到了一個(gè) Flag 對(duì)象,其名稱為 n、默認(rèn)參數(shù)值為 1234、值的類型為 intValue、幫助信息為 help message for flag n。并將這個(gè) Flag 對(duì)象保存在了 CommandLine 這個(gè)類型為 FlagSet 的結(jié)構(gòu)體指針對(duì)象的 formal 屬性中。
我們在示例程序中還使用了另外兩種方式定義標(biāo)志。
使用 flag.IntVar(&flagvar, "flagvar", 1234, "help message for flagvar") 定義標(biāo)志 -flagvar。
flag.IntVar 定義如下:
func IntVar(p *int, name string, value int, usage string) {
CommandLine.Var(newIntValue(value, p), name, usage)
}可以發(fā)現(xiàn),flag.IntVar 函數(shù)內(nèi)部沒有調(diào)用 CommandLine.Int 和 CommandLine.IntVar 的過程,而是直接調(diào)用 CommandLine.Var。
另外,我們還使用 flag.Var(&val, "val", "help message for val") 定義了 -val 標(biāo)志。
flag.Var 定義如下:
func Var(value Value, name string, usage string) {
CommandLine.Var(value, name, usage)
}flag.Var 函數(shù)內(nèi)部同樣直接調(diào)用了 CommandLine.Var,并且由于參數(shù) value 已經(jīng)是 Value 接口類型,可以無需調(diào)用 newIntValue 這類構(gòu)造函數(shù)將 Go 內(nèi)置類型轉(zhuǎn)為 Value 類型,直接傳遞參數(shù)即可。
2.2解析標(biāo)志參數(shù)
命令行參數(shù)定義完成了,終于到了解析部分,可以使用 flag.Parse() 解析命令行參數(shù)。
flag.Parse 函數(shù)代碼如下:
func Parse() {
CommandLine.Parse(os.Args[1:])
}內(nèi)部同樣是調(diào)用 CommandLine 對(duì)象對(duì)應(yīng)的方法,并且將除程序名稱以外的命令行參數(shù)都傳遞到 Parse 方法中,Parse 方法定義如下:
func (f *FlagSet) Parse(arguments []string) error {
f.parsed = true
f.args = arguments
for {
seen, err := f.parseOne()
if seen {
continue
}
if err == nil {
break
}
switch f.errorHandling {
case ContinueOnError:
return err
case ExitOnError:
if err == ErrHelp {
os.Exit(0)
}
os.Exit(2)
case PanicOnError:
panic(err)
}
}
return nil
}首先將 f.parsed 標(biāo)記為 true,在調(diào)用 f.Parsed() 方法時(shí)會(huì)被返回:
func (f *FlagSet) Parsed() bool {
return f.parsed
}接著又將 arguments 保存在 f.args 屬性中。
然后就是循環(huán)解析命令行參數(shù)的過程,每調(diào)用一次 f.parseOne() 解析一個(gè)標(biāo)志,直到解析完成或遇到 error 退出程序。
parseOne 方法實(shí)現(xiàn)如下:
func (f *FlagSet) parseOne() (bool, error) {
if len(f.args) == 0 {
return false, nil
}
s := f.args[0]
if len(s) < 2 || s[0] != '-' {
return false, nil
}
numMinuses := 1
if s[1] == '-' {
numMinuses++
if len(s) == 2 { // "--" terminates the flags
f.args = f.args[1:]
return false, nil
}
}
name := s[numMinuses:]
if len(name) == 0 || name[0] == '-' || name[0] == '=' {
return false, f.failf("bad flag syntax: %s", s)
}
// it's a flag. does it have an argument?
f.args = f.args[1:]
hasValue := false
value := ""
for i := 1; i < len(name); i++ { // equals cannot be first
if name[i] == '=' {
value = name[i+1:]
hasValue = true
name = name[0:i]
break
}
}
m := f.formal
flag, alreadythere := m[name] // BUG
if !alreadythere {
if name == "help" || name == "h" { // special case for nice help message.
f.usage()
return false, ErrHelp
}
return false, f.failf("flag provided but not defined: -%s", name)
}
if fv, ok := flag.Value.(boolFlag); ok && fv.IsBoolFlag() { // special case: doesn't need an arg
if hasValue {
if err := fv.Set(value); err != nil {
return false, f.failf("invalid boolean value %q for -%s: %v", value, name, err)
}
} else {
if err := fv.Set("true"); err != nil {
return false, f.failf("invalid boolean flag %s: %v", name, err)
}
}
} else {
// It must have a value, which might be the next argument.
if !hasValue && len(f.args) > 0 {
// value is the next arg
hasValue = true
value, f.args = f.args[0], f.args[1:]
}
if !hasValue {
return false, f.failf("flag needs an argument: -%s", name)
}
if err := flag.Value.Set(value); err != nil {
return false, f.failf("invalid value %q for flag -%s: %v", value, name, err)
}
}
if f.actual == nil {
f.actual = make(map[string]*Flag)
}
f.actual[name] = flag
return true, nil
}parseOne 代碼稍微多一點(diǎn),不過整體脈絡(luò)還是比較清晰的。
首先對(duì) f.args 參數(shù)進(jìn)行了校驗(yàn),接著提取標(biāo)志前導(dǎo)符號(hào) - 的個(gè)數(shù)放到 numMinuses 變量中,然后取出標(biāo)志名并對(duì)標(biāo)志語法做了檢查。
接下來取出參數(shù) value,并且判斷標(biāo)志名是否為 -help/-h,如果是則說明用戶只想打印程序使用幫助信息,打印后 parseOne 會(huì)返回 ErrHelp,上層的調(diào)用者 f.Parse 就會(huì)捕獲到 ErrHelp,然后調(diào)用 os.Exit(0) 直接退出程序。
其中 f.usage() 實(shí)現(xiàn)了打印幫助信息的功能,內(nèi)部具體實(shí)現(xiàn)這里就不講解了,因?yàn)榛旧鲜莾?nèi)容排版的實(shí)現(xiàn),不是核心功能,感興趣可以自己嘗試看一看。
最后就是根據(jù)參數(shù)值是否為 bool 類型分別進(jìn)行參數(shù)綁定,將參數(shù)設(shè)置到對(duì)應(yīng)的標(biāo)志變量中,并將標(biāo)志保存到 f.actual 中。
以上步驟都執(zhí)行完成后,在執(zhí)行 fmt.Printf("nFlag: %d\n", *nFlag) 時(shí),就能夠獲取到 nFlag 被賦予的參數(shù)值了。
至此,flag 包源碼的整體脈絡(luò)都已經(jīng)清晰了。
2.3其他代碼
在我們的示例代碼最后,還打印了 NFlag()、NArg()、Args()、Arg(1) 幾個(gè)函數(shù)的結(jié)果。
這幾個(gè)函數(shù)實(shí)現(xiàn)非常簡單,代碼如下:
func NFlag() int { return len(CommandLine.actual) }
func NArg() int { return len(CommandLine.args) }
func Args() []string { return CommandLine.args }
func Arg(i int) string {
return CommandLine.Arg(i)
}由于代碼過于簡單,我就不進(jìn)行解釋了,相信通過上面的講解,這幾個(gè)函數(shù)的作用你也能做到一目了然。
flag 包還有一些其他類型,如 stringValue、float64Value,這些類型實(shí)現(xiàn)思路都是一樣的,也不再一一講解。
最后,flag 包其他附屬的函數(shù)實(shí)現(xiàn),不是主要脈絡(luò),留給讀者自行查看學(xué)習(xí)。
3.總結(jié)
在開發(fā)命令行程序時(shí),Go 標(biāo)準(zhǔn)庫中的 flag 包是一個(gè)不錯(cuò)的選擇。
本文先對(duì) flag 包的基本使用進(jìn)行了演示,接著又對(duì)源碼進(jìn)行了深度剖析。
flag 包支持三種方式定義標(biāo)志,flag.Parse() 能夠?qū)γ钚袇?shù)進(jìn)行解析,解析成功后,就可以在代碼中使用參數(shù)值了。
以上就是深入探究Golang中flag標(biāo)準(zhǔn)庫的使用的詳細(xì)內(nèi)容,更多關(guān)于Golang flag標(biāo)準(zhǔn)庫的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
深入理解Go語言設(shè)計(jì)模式之函數(shù)式選項(xiàng)模式
在 Go 語言中,函數(shù)選項(xiàng)模式(Function Options Pattern)是一種常見且強(qiáng)大的設(shè)計(jì)模式,用于構(gòu)建可擴(kuò)展、易于使用和靈活的 API,本文就來看看它的具體用法吧2023-05-05
golang實(shí)現(xiàn)文件上傳并轉(zhuǎn)存數(shù)據(jù)庫功能
這篇文章主要為大家詳細(xì)介紹了golang實(shí)現(xiàn)文件上傳并轉(zhuǎn)存數(shù)據(jù)庫功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-07-07
Golang中HTTP服務(wù)的分析與設(shè)計(jì)詳解
這篇文章主要介紹了Golang中HTTP服務(wù)的分析與設(shè)計(jì),HTTP服務(wù)是實(shí)現(xiàn)Web應(yīng)用程序的重要組成部分,為了實(shí)現(xiàn)高效可擴(kuò)展的Web應(yīng)用程序,需要對(duì)HTTP服務(wù)進(jìn)行分析與設(shè)計(jì),需要的朋友可以參考下2023-05-05
深入解析Go語言中上下文超時(shí)與子進(jìn)程管理
這篇文章小編將通過一個(gè)實(shí)際問題的案例,和大家深入探討一下Go語言中的上下文超時(shí)和子進(jìn)程管理,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2023-10-10
go語言中sort包的實(shí)現(xiàn)方法與應(yīng)用詳解
golang中也實(shí)現(xiàn)了排序算法的包sort包,所以下面這篇文章主要給大家介紹了關(guān)于go語言中sort包的實(shí)現(xiàn)方法與應(yīng)用的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),需要的朋友們可以參考借鑒,下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧。2017-11-11

