Go에서 구성을 처리하는 방법 [닫기]


284

Go 프로그래밍을 처음 접했고 궁금한 점이 있습니다 .Go 프로그램의 구성 매개 변수를 처리하는 기본 방법은 무엇입니까 ( 다른 컨텍스트에서 속성 파일이나 ini 파일을 사용할 수있는 종류 )?


또한 몇 가지 추가 아이디어가 있는 golang-nuts 스레드 를 시작했습니다 .
theglauber

2
쉘 스크립트와 환경 변수를 사용하는 경향이 있습니다.
rightfold

3
필자는 전체 블로그 게시물 인 Persisting Application Configuration In Go 에서 가장 널리 사용되는 두 가지 형식 인 json과 YAML의 예제를 통해이를 수행하는 방법을 설명했습니다. 예제는 생산 준비가되었습니다.
upitau 2016 년

레코드를 위해 주석을 지원하고 JSON 및 UCL과 호환되는 HashiCorp의 HCL이 있습니다. github.com/hashicorp/hcl
Kaveh Shahbazian

답변:


244

JSON의 형식은 아주 잘 날 위해 일했습니다. 표준 라이브러리는 들여 쓰기 된 데이터 구조를 작성하는 방법을 제공하므로 읽기 쉽습니다.

이 golang-nuts thread 도 참조하십시오 .

JSON의 장점은 목록 및 매핑에 대한 의미론을 제공하면서도 구문 분석이 쉽고 사람이 읽기 쉽고 편집 할 수 있다는 점입니다 (매우 편리 할 수 ​​있음).

사용법 예 :

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]

6
JSON은 현재 대안 중 가장 나쁘지 않은 것 같습니다. 나는 go-yaml을 살펴 보았고 용감한 노력이지만 다른 곳을 봐야한다는 표시로 문서가 부족했습니다. goini 는 Windows ini 파일 을 처리 할 수있는 간단하고 쉬운 라이브러리 인 것 같습니다 . TOML이라는 새로운 형식이 제안되었지만 문제가 있습니다 . 이 시점에서 나는 JSON 또는 ini를 고수 할 것이다 .
theglauber

6
구성 파일의 모든 곳에 메모를 추가하려는 경우 YAML은 메모를 지원합니다.
Ivan Black

42
이 글을 읽고 그 경로를 내려가는 사람들에게는 JSON이 주석이 없기 때문에 사람이 사용할 수있는 구성 파일 (imo)에 적합하지 않습니다. 데이터 교환 형식입니다. 구성 파일에 도움이되는 / 설명 적 주석을 작성하는 기능이 손실되면 유지 관리 성이 손상 될 수 있습니다. ? "등).
Darian Moody

6
Ahhh-내 코드에서 시도해 보았고 대문자로 구조체 속성을 정의하는 것을 잊었습니다 (내 보낸 것이 아님). 어쩌면 다른 사람들도 같은 오류를 저지르고 경고를받을 것입니다.;
JohnGalt

6
defer file.Close()open err을 확인한 후 아마
Gabriel

97

또 다른 옵션은 Tom Preston-Werner가 만든 INI와 유사한 형식 인 TOML 을 사용 하는 것입니다. 나는 그것을 위해 이동 파서 내장 되어 광범위하게 테스트를 . 여기에 제안 된 다른 옵션처럼 사용할 수 있습니다. 예를 들어이 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
}

18
TOML은 줄 바꿈이나 줄 구성 설정 끝에 주석을 쓸 수 있기 때문에 좋아합니다. JSON으로는 그렇게 할 수 없습니다.
sergserg

각 구성 업데이트는 매우 성가신 코드 업데이트가 필요합니다.
hywak

4
구성에 대한 모든 접근 방식이 수행합니다. 프로그램이 새로운 설정을 어떻게 인식하고 있습니까?
BurntSushi5

@ BurntSushi5 Toml 파일에 코드가 신경 쓰지 않는 추가 필드가있을 수 있습니까? 새로운 버전의 구성 파일을 이전 버전의 코드와 함께 사용할 수 있습니까? 내 경우에는 사용하지 않는 구성 옵션을 무시해도됩니다.
user1952500 2018 년

2
나는 그것을 좋아한다. 잘 했어. 개인적으로 관리자 또는 고객이 JSON보다 TOML 파일을 변경하는 것이 더 쉽다고 생각합니다.
blndev

49

Viper 는 JSON, YAML 및 TOML과 함께 작동하는 golang 구성 관리 시스템입니다. 꽤 흥미로운 것 같습니다.


1
12factor 애플리케이션에 특히 실용적 12factor.net
DerKnorr

Go에서 JSON 구성에 gonfig를 사용하십시오. github.com/eduardbcom/gonfig
에두아르 Bondarenko

1
Viper를 사용하지 마십시오. 나에게 거의 해를 끼치는 스레드 안전하지 않습니다.
igonejack

@igonejack Viper가 어디서 물린 예를 제공해주세요.
Dr.eel

1
@ Dr.eel 다른 고 루틴에서 별도의 viper.GetBool ( "abc") 및 Viper.Set ( "abc", false)를 시도하십시오.
igonejack

44

더 복잡한 데이터 구조에는 일반적으로 JSON을 사용합니다. 단점은 사용자에게 오류의 위치, 다양한 에지 사례 및 그렇지 않은 것을 알려주는 많은 코드로 쉽게 끝날 수 있다는 것입니다.

기본 구성 (api 키, 포트 번호 등)의 경우 gcfg 패키지를 사용하는 것이 좋습니다 . git config 형식을 기반으로합니다.

설명서에서 :

샘플 구성 :

; 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")

슬라이스 값도 지원하므로 키를 여러 번 지정할 수 있으며 이와 같은 다른 멋진 기능을 사용할 수 있습니다.


4
gcfg 의 최초 작성자 는 프로젝트를 중단하고 다른 관련 sconf를 시작 했습니다 .
iwat

39

iniflags 와 함께 표준 go 플래그를 사용 하십시오 .

표준 이동 플래그는 다음과 같은 이점이 있습니다.

  • 관용적.
  • 사용하기 쉬운. 프로젝트에서 사용하는 임의의 패키지에 플래그를 쉽게 추가하고 뿌릴 수 있습니다.
  • 플래그는 기본값 및 설명을 기본적으로 지원합니다.
  • 플래그는 표준 '도움말'출력에 기본값 및 설명을 제공합니다.

유일한 단점은 표준 go 플래그입니다-앱에 사용되는 플래그 수가 너무 많을 때 관리 문제입니다.

Iniflags는이 문제를 우아하게 해결합니다. 기본 패키지에서 두 줄을 수정하면 ini 파일에서 플래그 값을 읽는 데 도움이됩니다. 명령 행에서 새 값을 전달하여 ini 파일의 플래그를 대체 할 수 있습니다.

자세한 내용은 https://groups.google.com/forum/#!topic/golang-nuts/TByzyPgoAQE 를 참조하십시오.


내가 작업 한 프로젝트 (처음부터 스크래치 golang 프로젝트)에 플래그를 사용하기 시작했지만 테스트와 같은 것을 처리하는 방법이 궁금합니다. 예를 들어, 이것은 api 클라이언트이며 플래그를 사용하고 싶지만 go test구성 파일이 아닌 테스트를 복잡하게하는 것처럼 보입니다 ( 플래그를 전달하지 못함).
zachaysan

테스트에서 플래그를 설정하는 것은 쉽습니다.*FlagName = value
Steven Soroka

9
여기에 실제 예제를 보여주는 자세한 예제 코드가 있다면 매우 도움이 될 것입니다 :)
zero_cool

다른 언어로 작성된 다른 응용 프로그램과 구성을 공유해야 할 때는 좋지 않습니다.
Kirzilla

플래그 대신 pflags를 사용하는 것이 좋습니다. pflags는 POSIX 표준 사용
Fjolnir 드보르작

12

Ini와 유사한 파일을 사용 하는 Gcfg 를 사용 하기 시작했습니다 . 간단합니다-간단한 것을 원한다면 좋은 선택입니다.

현재 사용중인 로딩 코드는 다음과 같습니다. 기본 설정이 있으며 일부 구성을 재정의하는 명령 줄 플래그 (표시되지 않음)를 허용합니다.

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가 이미 언급 한 내용이 아닙니까?
nemo

8

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)

전체 구성 구조를 다시 정의 할 필요가 없기
때문에이 방법이 좋습니다



5

golang에 간단한 ini 구성 라이브러리를 작성했습니다.

https://github.com/c4pt0r/cfg

고 루틴 안전하고 사용하기 쉬운

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

"flag"패키지를 사용하는 것처럼 INI를 구문 분석 할 수 있습니다.

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

당신은 또한에 관심이있을 수 있습니다 범용 구성 언어 인 UCL에 대한 Go 바인딩 세트 인 go-libucl에 . UCL은 JSON과 비슷하지만 사람을 더 잘 지원합니다. 주석과 SI 승수 (10k, 40M 등)와 같은 사람이 읽을 수있는 구문을 지원하며 보일러 플레이트 (예 : 키 주위 인용 부호)가 약간 줄어 듭니다. 이미 익숙하다면 nginx 구성 파일 형식에 가깝습니다.


2

니모에 동의합니다 하고 모든 것을 쉽게 만들 수있는 작은 도구를 썼습니다.

bitbucket.org/gotamer/cfg 는 json 구성 패키지입니다

  • 애플리케이션에서 구성 항목을 구조체로 정의합니다.
  • 구조체의 json 구성 파일 템플릿이 첫 번째 실행에 저장됩니다.
  • 런타임 수정 사항을 구성에 저장할 수 있습니다

예제는 doc.go를 참조하십시오


1

JSON을 사용해 보았습니다. 효과가있었습니다. 그러나 나는 내가 설정할 정확한 필드와 유형의 구조체를 만들어야하는 것을 싫어합니다. 나에게 그것은 고통이었다. 내가 찾은 모든 구성 옵션이 사용하는 방법이라는 것을 알았습니다. 역동적 인 언어에 대한 나의 배경이 그런 장황함의 이점에 대해 눈을 멀게 할 수도 있습니다. 새로운 간단한 구성 파일 형식을 만들고 더 역동적 인 lib를 작성했습니다.

https://github.com/chrisftw/ezconf

나는 Go 세계에 익숙하지 않아 Go Go가 아닐 수도 있습니다. 그러나 그것은 효과적이고 매우 빠르며 사용하기가 매우 간단합니다.

찬성

  • 매우 간단
  • 적은 코드

단점

  • 배열 또는 맵 유형이 없음
  • 매우 평평한 파일 형식
  • 비표준 conf 파일
  • Go 커뮤니티에서 일반적으로 눈살을 찌푸 리면 약간의 컨벤션이 내장되어 있습니다. (config 디렉토리에서 구성 파일을 찾습니다)
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.