Go'da yapılandırma nasıl işlenir [kapalı]


284

Go programlamada yeniyim ve merak ediyorum: bir Go programı için yapılandırma parametrelerini işlemek için tercih edilen yol nedir (bir tür özellik dosyalarını veya ini dosyalarını başka bağlamlarda kullanabilir)?


Ayrıca birkaç ek fikri olan bir golang-nut ipliği başlattım .
theglauber

2
Kabuk betikleri ve ortam değişkenleri kullanma eğilimindeyim.
sağ kanat

3
Bütün bir blog gönderisini adadım Persisting Application Configuration In Go , en popüler iki biçime örneklerle nasıl yapılacağını açıkladım: json ve YAML. Örnekler üretime hazırdır.
upitau

Sadece kayıt için, yorumları destekleyen ve JSON ve UCL uyumlu olan HashiCorp'tan HCL var. Github.com/hashicorp/hcl
Kaveh

Yanıtlar:


244

JSON biçimi oldukça iyi benim için çalıştı. Standart kütüphane girintili veri yapısını yazmak için yöntemler sunar, bu yüzden oldukça okunabilir.

Ayrıca bkz bu golang-fındık iplik .

JSON'un faydaları, listeler ve eşlemeler için semantikler sunarken (oldukça kullanışlı olabilir) ayrıştırmanın ve insan tarafından okunabilir / düzenlenebilir olmasının oldukça basit olmasıdır, ki bu birçok ini tipi yapılandırma ayrıştırıcısında durum böyle değildir.

Örnek kullanım:

conf.json :

{
    "Users": ["UserA","UserB"],
    "Groups": ["GroupA"]
}

Yapılandırmayı okumak için program

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]

6
Görünüşe göre JSON mevcut alternatiflerden en az kötü olanı. Go-yaml içine baktım ve bu cesur bir çaba, ama ben başka bir yere bakmak gerektiğini bir gösterge olarak belge eksikliği aldı. goini, Windows ini dosyalarını işlemek için basit ve kolay bir kütüphane gibi görünüyor . TOML adında yeni bir biçim önerildi, ancak sorunları da var . Bu noktada JSON veya ini'ye yapışırdım .
theglauber

6
Config dosyasının her yerine not eklemek istiyorsanız YAML yorumları destekler.
Ivan Black

43
Bunu okuyan ve bu rotaya gidenler için dikkatli olun: JSON'un yorum eksikliği, insan tarafından kullanılabilir bir yapılandırma dosyası (imo) için uygun değildir. Bu bir veri değişim formatıdır - yapılandırma dosyalarına yararlı / açıklayıcı yorumlar yazma yeteneğini kaybetmenin sürdürülebilirliğini bozabilir ("bu ayar neden etkinleştirilir?", "Ne işe yarar?", "Bunun için geçerli değerler nelerdir?" ?" vb).
Darian Moody

6
Ahhh - Bunu kodumda denedim ve yapı niteliklerini büyük harflerle (dışa aktarılmadı) tanımlamayı unuttum - bu bana hayatımın bir saatine mal oldu. Belki başkaları da aynı hatayı
yaparlar

6
Muhtemelen defer file.Close()açık hata kontrol ettikten sonra
Gabriel

97

Başka bir seçenek de Tom Preston-Werner tarafından oluşturulan INI benzeri bir format olan TOML kullanmaktır . Ben bunun için bir git ayrıştırıcı inşa edilmiştir kapsamlı olarak test . Burada önerilen diğer seçenekler gibi kullanabilirsiniz. Örneğin, bu TOML verilerine sahipsenizsomething.toml

Age = 198
Cats = [ "Cauchy", "Plato" ]
Pi = 3.14
Perfection = [ 6, 28, 496, 8128 ]
DOB = 1987-07-05T05:45:00Z

Ardından Go programınıza benzer bir şeyle yükleyebilirsiniz.

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
}

18
TOML'ı seviyorum çünkü yeni satırlara veya satır yapılandırma ayarının sonuna yorum yazmama izin veriyor. JSON ile yapamam.
sergserg

Her yapılandırma güncellemesi çok can sıkıcı olan kodda güncelleme gerektirir.
hywak

4
Konfigürasyon için her yaklaşım yapar. Programınız yeni yapılandırmadan başka nasıl haberdar olabilir?
BurntSushi5

@ BurntSushi5 Toml dosyasında kodun umurunda olmadığı ekstra alanlar olabilir mi? Yani, config dosyasının daha yeni bir sürümü kodun eski sürümüyle kullanılabilir mi? Benim durumumda, kullanılmayan yapılandırma seçeneklerini yok saymak sorun değil.
user1952500

2
bunu sevdim. İyi iş. Şahsen ben bir JSON daha yöneticileri veya müşterileri bir TOML dosyasını değiştirmek için daha kolay olduğunu düşünüyorum.
blndev

49

Viper , JSON, YAML ve TOML ile çalışan bir golang yapılandırma yönetim sistemidir. Oldukça ilginç görünüyor.


1
12factor uygulamaları için özellikle uygundur 12factor.net
DerKnorr

Go'daki JSON yapılandırması için gonfig kullanın. github.com/eduardbcom/gonfig
Eduard Bondarenko

1
Viper kullanmayın, neredeyse beni işten çıkaran iplik güvenli değil.
igonejack

@igonejack Lütfen Viper'ın sizi nerede ısırdığı bir örnek verin?
Dr.Eel

1
@ Dr.eel Farklı goroutine ayrı viper.GetBool ("abc") ve Viper.Set ("abc", yanlış) deneyin.
igonejack

44

Daha karmaşık veri yapıları için genellikle JSON kullanıyorum. Dezavantajı, hatanın nerede olduğunu, çeşitli kenar durumlarını ve ne olmadığını kullanıcıya bildirmek için kolayca bir grup kodla sonlandırmanızdır.

Taban yapılandırması için (api anahtarları, bağlantı noktası numaraları, ...) gcfg paketi ile çok iyi şanslar yaşadım . Git yapılandırma biçimini temel alır.

Belgelerden:

Örnek yapılandırma:

; Comment line
[section]
name = value # Another comment
flag # implicit value for bool is true

Yapıya git:

type Config struct {
    Section struct {
            Name string
            Flag bool
    }
}

Ve kodu okumak için gerekli:

var cfg Config
err := gcfg.ReadFileInto(&cfg, "myconfig.gcfg")

Ayrıca dilim değerlerini de destekler, böylece bir anahtarın birden çok kez belirtilmesine ve bunun gibi diğer güzel özelliklere izin verebilirsiniz.


4
Orijinal gcfg yazarı projeyi durdurdu ve başka bir ilgili sconf başlattı .
iwat

39

Sadece iniflags ile standart go bayrakları kullanın .

Standart go bayraklarının aşağıdaki avantajları vardır:

  • Deyimsel.
  • Kullanımı kolay. Bayraklar, projenizin kullandığı rastgele paketlere kolayca eklenebilir ve dağıtılabilir.
  • Bayraklarda varsayılan değerler ve açıklama için hazır destek bulunur.
  • Bayraklar, varsayılan değerler ve açıklama ile standart 'yardım' çıktısı sağlar.

Standart go bayraklarının tek dezavantajı, uygulamanızda kullanılan bayrakların sayısı çok fazla olduğunda yönetim sorunlarıdır.

Iniflags bu sorunu zarif bir şekilde çözer: sadece ana paketinizdeki iki satırı değiştirin ve ini dosyasından bayrak değerlerini okumak için sihirli bir şekilde destek kazanır. İni dosyalarındaki bayraklar, komut satırına yeni değerler iletilerek geçersiz kılınabilir.

Ayrıntılar için ayrıca https://groups.google.com/forum/#!topic/golang-nuts/TByzyPgoAQE adresine bakın.


Üzerinde çalıştığım bir proje için bayraklar kullanmaya başladım (ilk sıfırdan golang projem), ama testler gibi şeylerle nasıl başa çıkacağımı merak ediyorum. Örneğin, bu bir api istemcisi ve bayrakları kullanmak istiyorum, ancak go testbir yapılandırma dosyası istemezken testimi (bayrakları geçirmeme izin vermiyor) karmaşık hale getirecek gibi görünüyor .
zachaysan

Testlerden bayrak ayarlamak kolaydır:*FlagName = value
Steven Soroka

9
burada çalışan bir örnek gösteren ayrıntılı örnek kodu olsaydı çok yardımcı olur :)
zero_cool

Yapılandırmayı başka dillerde yazılmış diğer uygulama parçalarıyla paylaşmanız gerektiğinde iyi bir fikir değildir.
Kirzilla

bayrak yerine pflags kullanılmasını önerir. pflags posix standardını kullanıyor
Fjolnir Dvorak

12

Ini benzeri dosyaları kullanan Gcfg kullanmaya başladım . Çok basit - basit bir şey istiyorsanız, bu iyi bir seçimdir.

Şu anda kullanıyorum, varsayılan ayarları olan ve benim yapılandırma bazılarını geçersiz kılan komut satırı bayraklarına (gösterilmiyor) izin veren yükleme kodu:

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
}

2
Ask'in bahsettiği şey tam olarak bu değil mi?
nemo

8

gonfig'a bir bak

// 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)

Bu iyi, çünkü go tüm yapılandırma yapısını yeniden tanımlamak zorunda değilim
thanhpk



5

Golang'da basit bir ini yapılandırma kütüphanesi yazdım.

https://github.com/c4pt0r/cfg

goroutin güvenli, kullanımı kolay

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)
    }
}

=================== Güncelleme =======================

Son zamanlarda bölüm desteğine sahip bir INI ayrıştırıcıya ihtiyacım var ve basit bir paket yazıyorum:

github.com/c4pt0r/cfg

u "bayrak" paketini kullanmak gibi INI ayrıştırabilirsiniz:

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)
}

4

Ayrıca , Evrensel Yapılandırma Dili UCL için bir dizi Go bağı olan go-libucl ile de ilgilenebilirsiniz . UCL biraz JSON'a benzer, ancak insanlar için daha iyi bir destekle: SI çarpanları (10k, 40M, vb.) Gibi yorumları ve insan tarafından okunabilir yapıları destekler ve biraz daha az kazan plakası vardır (örneğin, anahtarların etrafındaki alıntılar). Zaten aşina iseniz, nginx yapılandırma dosyası formatına oldukça yakındır.


2

Nemo ile hemfikirim ve hepsini kolaylaştırmak için küçük bir araç yazdım.

bitbucket.org/gotamer/cfg bir json yapılandırma paketidir

  • Uygulamanızdaki yapılandırma öğelerinizi bir yapı olarak tanımlarsınız.
  • Yapınızdaki bir json yapılandırma dosyası şablonu ilk çalıştırmada kaydedilir
  • Çalışma zamanı değişikliklerini yapılandırmaya kaydedebilirsiniz

Örnek için doc.go'ya bakınız.


1

JSON'u denedim. İşe yaradı. Ama ayarlayabileceğim alanların ve türlerin yapısını oluşturmaktan nefret ediyorum. Bana göre bu bir acıydı. Ben bulabildiğim tüm yapılandırma seçenekleri tarafından kullanılan yöntem olduğunu fark ettim. Belki dinamik dillerdeki geçmişim beni bu tür ayrıntıların yararlarına kör ediyor. Yeni bir basit yapılandırma dosyası biçimi ve okumak için daha dinamik bir ish lib yaptım.

https://github.com/chrisftw/ezconf

Go dünyasında oldukça yeniyim, bu yüzden Go yolu olmayabilir. Ama işe yarıyor, oldukça hızlı ve kullanımı çok basit.

Artıları

  • Süper basit
  • Daha az kod

Eksileri

  • Diziler veya Harita türleri yok
  • Çok düz dosya formatı
  • Standart olmayan conf dosyaları
  • Go topluluğunda genel olarak kaşlarını çattıysam, küçük bir kongre var. (Yapılandırma dizinindeki yapılandırma dosyasını arar)
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.