4.9 آموزش کار با toml

4.9 آموزش کار با toml

4.9.1 مقدمه #

فایل‌های TOML یک نمونه از فایل‌های پیکربندی هستند که در سیستم‌های مدرن مورد استفاده قرار می‌گیرند، این فایل‌ها به صورت متنی و قابل خواندن برای انسان و در عین حال قابل پردازش برای ماشین طراحی شده‌اند.

TOML مخفف کلمات (Tom’s Obvious, Minimal Language) می‌باشد. جمعیت بزرگتری از افراد آن را مفسرند به این شکل که TOML ابزاری ساده برای پیکربندی بسیار درون‌فرمانی است. این فرمت فایل متنی دارای مقادیر شبیه به دیکشنری بوده و در بسیاری از نرم‌افزارها، به‌طور خاص در نرم‌افزارهای ساخته شده با golang بسیار به‌کار می‌رود.

مثال زیر یک فایل TOML معتبر را نمایش می‌دهد:

1[database]
2server = "localhost"
3port = 3306
4user = "username"
5password = "password"
6database = "myDB"

در این مثال، تمام اطلاعات پیکربندی مربوط به یک پایگاه‌داده وجود دارد (server، port، user و غیره)، و به صورت مشخصی تعریف شده‌اند، به طوری که برای برنامه‌نویسی با استفاده از این پیکربندی بسیار سرعت‌بخش خواهد بود. از آنجا که فایل TOML قابل‌خواندی و ویرایش توسط انسان است، برنامه‌نویسی با این نوع فایل‌ها آسان و قابل فهم خواهد بود.

4.9.2 کار با marshal و unmarshal پکیج toml #

پکیج toml در زبان Go، حاوی توابع Marshal و Unmarshal برای تبدیل داده‌های Go به فرمت TOML و برعکس می‌باشد.

4.9.2.1 Marshal #

تابع Marshal برای تبدیل یک متغیر ساخته شده در Go به فرمت TOML مورد استفاده قرار می‌گیرد. برای استفاده از این تابع، باید داده‌های خود را به یک متغیر با نوع interface{} تبدیل کنید و سپس این متغیر را به تابع Marshal بدهید.

به عنوان مثال، برای تبدیل داده‌های map[string]interface{} به فرمت TOML، می‌توانید این کد را به کار ببرید:

 1package main
 2
 3import (
 4    "github.com/BurntSushi/toml"
 5    "fmt"
 6)
 7
 8func main() {
 9    data := map[string]interface{}{
10        "name":  "John",
11        "email": "john@example.com",
12        "age":   22,
13    }
14    tomlData, err := toml.Marshal(data)
15    if err != nil {
16        panic(err)
17    }
18    fmt.Println(string(tomlData))
19}

این کد یک دیکشنری ساده را تعریف می‌کند و سپس آن را به فرمت TOML تبدیل می‌کند. خروجی به صورت زیر خواهد بود:

1$ go run main.go
2age = 22
3email = "john@example.com"
4name = "John"

4.9.2.2 Unmarshal #

تابع Unmarshal، برای تبدیل یک رشته فرمت TOML به داده‌های Go استفاده می‌شود. برای استفاده از این تابع، باید با استفاده از تابع ioutil.ReadFile، فایل TOML مورد نظر را بخوانید و سپس رشته خوانده‌شده را به تابع Unmarshal بدهید.

به عنوان مثال، برای خواندن یک فایل TOML و تبدیل آن به یک دیکشنری در Go، می‌توانید این کد را به کار ببرید:

 1package main
 2
 3import (
 4    "github.com/BurntSushi/toml"
 5    "fmt"
 6    "io/ioutil"
 7)
 8
 9type Person struct {
10    Name  string
11    Email string
12    Age   int
13}
14
15func main() {
16    data, err := ioutil.ReadFile("file.toml")
17    if err != nil {
18        panic(err)
19    }
20
21    var person Person
22    if _, err := toml.Decode(string(data), &person); err != nil {
23        panic(err)
24    }
25
26    fmt.Printf("%#v\n", person)
27}

این کد یک فایل TOML با فرمت زیر را می‌خواند و مقادیر موجود در آن را به داده‌های Go مناسب تبدیل می‌کند:

1name = "John"
2email = "john@example.com"
3age = 22

خروجی به صورت زیر خواهد بود:

1$ go run main.go
2main.Person{Name:"John", Email:"john@example.com", Age:22}

4.9.3 تبدیل struct به toml و بلعکس #

برای تبدیل یک struct به فرمت TOML و بلعکس، می‌توان از تابع‌های Marshal و Unmarshal پکیج toml استفاده کرد. در این روش، فیلدهای struct بر اساس نام آن‌ها و به صورت حروف کوچک در فایل TOML با نام فیلد متناظر ذخیره می‌شوند.

همچنین می‌توان از تگ‌ها در داخل struct برای تعیین نام فیلد در فایل TOML استفاده کرد. با استفاده از تگ toml:"name" می‌توان نامی دلخواه برای فیلد در فایل TOML مشخص کرد. همچنین می‌توان از تگ‌های دیگری مانند toml:"omitempty" برای اجباری نبودن یک فیلد در فایل TOML استفاده کرد.

به عنوان مثال، فرض کنید یک struct به نام Person با فیلدهای Name، Emailو Age داریم. با استفاده از تگ‌ها، نام فیلدها در فایل TOML و پیش‌فرض برای آن‌ها مشخص می‌شود.

 1package main
 2
 3import (
 4    "github.com/BurntSushi/toml"
 5    "fmt"
 6)
 7
 8type Person struct {
 9    Name  string `toml:"name"`
10    Email string `toml:"email,omitempty"`
11    Age   int    `toml:"age"`
12}
13
14func main() {
15    // Marshaling from struct to TOML
16    person := Person{Name: "John", Age: 30}
17    tomlData, err := toml.Marshal(person)
18    if err != nil {
19        panic(err)
20    }
21    fmt.Println(string(tomlData))
22
23    // Unmarshaling from TOML to struct
24    var p Person
25    if _, err := toml.Decode(string(tomlData), &p); err != nil {
26        panic(err)
27    }
28    fmt.Printf("%#v\n", p)
29}

در این مثال، struct با نام Person تعریف شده و از تگ برای نام‌گذاری فیلدها استفاده شده است. در تابع main، ابتدا از متد Marshal پکیج toml برای تبدیل یک شیء Person به فرمت TOML استفاده شده است. سپس با استفاده از متد Decode از پکیج toml، فایل TOML به داخل شیء Person تبدیل می‌شود.

خروجی کد بالا به صورت زیر است:

1$ go run main.go
2name = "John"
3age = 30
4
5main.Person{Name:"John", Email:"", Age:30}

همان‌طور که مشاهده می‌کنید، نام فیلدها در فایل TOML با تگ‏های تعیین‌شده در struct مطابقت می‌کند. همچنین با توجه به تگ omitempty که در فیلد Email وجود دارد، این فیلد در فایل TOML نمایش داده نشده است، چرا که در شی person مقداری برای آن تعریف نشده بود.