ฉันใหม่ในการเขียนโปรแกรม Go และฉันสงสัยว่า: วิธีใดที่เหมาะสมในการจัดการพารามิเตอร์การกำหนดค่าสำหรับโปรแกรม Go (ประเภทของสิ่งหนึ่งที่อาจใช้ไฟล์คุณสมบัติหรือไฟล์iniสำหรับในบริบทอื่น ๆ )?
ฉันใหม่ในการเขียนโปรแกรม Go และฉันสงสัยว่า: วิธีใดที่เหมาะสมในการจัดการพารามิเตอร์การกำหนดค่าสำหรับโปรแกรม Go (ประเภทของสิ่งหนึ่งที่อาจใช้ไฟล์คุณสมบัติหรือไฟล์iniสำหรับในบริบทอื่น ๆ )?
คำตอบ:
JSONรูปแบบทำงานให้ฉันได้ค่อนข้างดี ไลบรารีมาตรฐานเสนอวิธีการในการเขียนโครงสร้างข้อมูลที่มีการเยื้องจึงค่อนข้างอ่านได้
ดูเพิ่มเติมด้าย golang ถั่วนี้
ประโยชน์ของ JSON คือการแยกวิเคราะห์และอ่าน / แก้ไขได้ง่ายในขณะที่ให้ความหมายสำหรับรายการและการแมป (ซึ่งอาจเป็นประโยชน์มาก) ซึ่งไม่ใช่กรณีที่มี parsers config แบบ ini จำนวนมาก
ตัวอย่างการใช้งาน:
conf.json :
{
"Users": ["UserA","UserB"],
"Groups": ["GroupA"]
}
โปรแกรมอ่านการกำหนดค่า
import (
"encoding/json"
"os"
"fmt"
)
type Configuration struct {
Users []string
Groups []string
}
file, _ := os.Open("conf.json")
defer file.Close()
decoder := json.NewDecoder(file)
configuration := Configuration{}
err := decoder.Decode(&configuration)
if err != nil {
fmt.Println("error:", err)
}
fmt.Println(configuration.Users) // output: [UserA, UserB]
defer file.Close()
หลังจากตรวจสอบข้อผิดพลาดที่เปิดอยู่
อีกทางเลือกหนึ่งคือใช้TOMLซึ่งเป็นรูปแบบ INI ที่สร้างโดย Tom Preston-Werner ฉันสร้าง parser ไปได้ที่มีการทดสอบอย่างกว้างขวาง คุณสามารถใช้งานได้เหมือนกับตัวเลือกอื่น ๆ ที่เสนอไว้ที่นี่ ตัวอย่างเช่นหากคุณมีข้อมูล TOML นี้something.toml
Age = 198
Cats = [ "Cauchy", "Plato" ]
Pi = 3.14
Perfection = [ 6, 28, 496, 8128 ]
DOB = 1987-07-05T05:45:00Z
จากนั้นคุณสามารถโหลดลงในโปรแกรม Go ของคุณด้วยสิ่งที่ชอบ
type Config struct {
Age int
Cats []string
Pi float64
Perfection []int
DOB time.Time
}
var conf Config
if _, err := toml.DecodeFile("something.toml", &conf); err != nil {
// handle error
}
Viperเป็นระบบจัดการการกำหนดค่า golang ที่ทำงานร่วมกับ JSON, YAML และ TOML มันดูน่าสนใจทีเดียว
ฉันมักจะใช้ JSON สำหรับโครงสร้างข้อมูลที่ซับซ้อนมากขึ้น ข้อเสียคือคุณท้ายรหัสได้ง่าย ๆ เพื่อบอกผู้ใช้ว่าเกิดข้อผิดพลาดกรณีขอบต่าง ๆ และอะไรบ้าง
สำหรับการตั้งค่าพื้นฐาน (คีย์ api, หมายเลขพอร์ต, ... ) ฉันโชคดีมากกับแพ็คเกจgcfg มันขึ้นอยู่กับรูปแบบการกำหนดค่า git
จากเอกสาร:
ตัวอย่างการกำหนดค่า:
; Comment line
[section]
name = value # Another comment
flag # implicit value for bool is true
ไป struct:
type Config struct {
Section struct {
Name string
Flag bool
}
}
และรหัสที่จำเป็นในการอ่าน:
var cfg Config
err := gcfg.ReadFileInto(&cfg, "myconfig.gcfg")
นอกจากนี้ยังรองรับค่าชิ้นดังนั้นคุณสามารถอนุญาตให้ระบุคีย์ได้หลายครั้งและคุณสมบัติที่ดีอื่น ๆ เช่นนั้น
เพียงแค่ใช้มาตรฐานธงไปกับiniflags
ธงแบบมาตรฐานไปมีประโยชน์ดังต่อไปนี้:
ข้อเสียเปรียบธงมาตรฐานแบบย้อนกลับเท่านั้นที่มี - คือปัญหาการจัดการเมื่อจำนวนของค่าสถานะที่ใช้ในแอปของคุณใหญ่เกินไป
Iniflags แก้ปัญหานี้ได้อย่างหรูหรา: เพียงแค่แก้ไขสองบรรทัดในแพ็คเกจหลักของคุณและมันจะได้รับการสนับสนุนอย่างน่าอัศจรรย์สำหรับการอ่านค่าสถานะจากไฟล์ ini การตั้งค่าสถานะจากไฟล์ ini สามารถ overriden โดยผ่านค่าใหม่ในบรรทัดคำสั่ง
ดูเพิ่มเติมที่https://groups.google.com/forum/#!topic/golang-nuts/TByzyPgoAQEสำหรับรายละเอียด
go test
ไม่อนุญาตให้ฉันส่งผ่านค่าสถานะ) ในขณะที่ไฟล์ปรับแต่งจะไม่ทำงาน
*FlagName = value
ฉันเริ่มใช้Gcfgซึ่งใช้ไฟล์ Ini-like มันง่าย - ถ้าคุณต้องการอะไรที่เรียบง่ายนี่เป็นตัวเลือกที่ดี
นี่คือรหัสการโหลดที่ฉันใช้อยู่ในปัจจุบันซึ่งมีการตั้งค่าเริ่มต้นและอนุญาตให้ใช้แฟล็กบรรทัดคำสั่ง (ไม่แสดง) ที่แทนที่การตั้งค่าบางอย่างของฉัน:
package util
import (
"code.google.com/p/gcfg"
)
type Config struct {
Port int
Verbose bool
AccessLog string
ErrorLog string
DbDriver string
DbConnection string
DbTblPrefix string
}
type configFile struct {
Server Config
}
const defaultConfig = `
[server]
port = 8000
verbose = false
accessLog = -
errorLog = -
dbDriver = mysql
dbConnection = testuser:TestPasswd9@/test
dbTblPrefix =
`
func LoadConfiguration(cfgFile string, port int, verbose bool) Config {
var err error
var cfg configFile
if cfgFile != "" {
err = gcfg.ReadFileInto(&cfg, cfgFile)
} else {
err = gcfg.ReadStringInto(&cfg, defaultConfig)
}
PanicOnError(err)
if port != 0 {
cfg.Server.Port = port
}
if verbose {
cfg.Server.Verbose = true
}
return cfg.Server
}
ดูที่gonfig
// load
config, _ := gonfig.FromJson(myJsonFile)
// read with defaults
host, _ := config.GetString("service/host", "localhost")
port, _ := config.GetInt("service/port", 80)
test, _ := config.GetBool("service/testing", false)
rate, _ := config.GetFloat("service/rate", 0.0)
// parse section into target structure
config.GetAs("service/template", &template)
https://github.com/spf13/viperและhttps://github.com/zpatrick/go-configเป็นห้องสมุดที่ค่อนข้างดีสำหรับไฟล์กำหนดค่า
ใช้Tomlเช่นบทความนี้การอ่านไฟล์ config ทางไป
ฉันเขียนไลบรารี่ของ ini config ใน golang
โกโรไทน์ปลอดภัยใช้งานง่าย
package cfg
import (
"testing"
)
func TestCfg(t *testing.T) {
c := NewCfg("test.ini")
if err := c.Load() ; err != nil {
t.Error(err)
}
c.WriteInt("hello", 42)
c.WriteString("hello1", "World")
v, err := c.ReadInt("hello", 0)
if err != nil || v != 42 {
t.Error(err)
}
v1, err := c.ReadString("hello1", "")
if err != nil || v1 != "World" {
t.Error(err)
}
if err := c.Save(); err != nil {
t.Error(err)
}
}
=================== ปรับปรุง =======================
เมื่อเร็ว ๆ นี้ฉันต้องการตัวแยกวิเคราะห์ INI พร้อมส่วนสนับสนุนและฉันเขียนแพ็คเกจง่าย ๆ :
github.com/c4pt0r/cfg
คุณสามารถแยก INI เช่นใช้แพ็คเกจ "flag":
package main
import (
"log"
"github.com/c4pt0r/ini"
)
var conf = ini.NewConf("test.ini")
var (
v1 = conf.String("section1", "field1", "v1")
v2 = conf.Int("section1", "field2", 0)
)
func main() {
conf.Parse()
log.Println(*v1, *v2)
}
คุณอาจสนใจgo-libuclชุดของการเชื่อม Go สำหรับ UCL ภาษา Universal Configuration UCL เป็นเหมือน JSON แต่ด้วยการสนับสนุนที่ดีกว่าสำหรับมนุษย์: รองรับความคิดเห็นและโครงสร้างที่มนุษย์อ่านได้เช่น SI ทวีคูณ (10k, 40M, ฯลฯ ) และมีสำเร็จรูปน้อยกว่าเล็กน้อย (เช่นคำพูดรอบคีย์) ที่จริงแล้วมันค่อนข้างใกล้เคียงกับรูปแบบไฟล์กำหนดค่า nginx หากคุณคุ้นเคยกับมันแล้ว
ฉันเห็นด้วยกับnemoและฉันเขียนเครื่องมือเล็กน้อยเพื่อให้ง่ายขึ้น
bitbucket.org/gotamer/cfgเป็นแพ็คเกจการกำหนดค่า json
ดู doc.go สำหรับตัวอย่าง
ฉันลอง JSON มันได้ผล แต่ฉันเกลียดที่จะต้องสร้างโครงสร้างของฟิลด์และประเภทที่แน่นอนที่ฉันอาจตั้งค่า สำหรับฉันนั่นเป็นความเจ็บปวด ฉันสังเกตว่ามันเป็นวิธีการที่ใช้โดยตัวเลือกการกำหนดค่าทั้งหมดที่ฉันสามารถหาได้ บางทีภูมิหลังของฉันในภาษาแบบไดนามิกอาจทำให้ฉันตาบอดกับประโยชน์ของการใช้คำฟุ่มเฟื่อยดังกล่าว ฉันสร้างรูปแบบไฟล์กำหนดค่าแบบง่ายและ lib-ish แบบไดนามิกมากขึ้นสำหรับการอ่านออก
https://github.com/chrisftw/ezconf
ฉันค่อนข้างใหม่สำหรับโลก Go ดังนั้นอาจไม่ใช่วิธี Go แต่มันใช้งานได้มันค่อนข้างเร็วและใช้ง่ายสุด ๆ