Migrate to dep (#3972)
* Update makefile to use dep * Migrate to dep * Fix some deps * Try to find a better version for golang.org/x/net * Try to find a better version for golang.org/x/oauth2
This commit is contained in:
parent
d7fd9bf7bb
commit
3f3383dc0a
281 changed files with 12024 additions and 32676 deletions
16
vendor/gopkg.in/alexcesaro/quotedprintable.v3/README.md
generated
vendored
16
vendor/gopkg.in/alexcesaro/quotedprintable.v3/README.md
generated
vendored
|
@ -1,16 +0,0 @@
|
|||
# quotedprintable
|
||||
|
||||
## Introduction
|
||||
|
||||
Package quotedprintable implements quoted-printable and message header encoding
|
||||
as specified by RFC 2045 and RFC 2047.
|
||||
|
||||
It is a copy of the Go 1.5 package `mime/quotedprintable`. It also includes
|
||||
the new functions of package `mime` concerning RFC 2047.
|
||||
|
||||
This code has minor changes with the standard library code in order to work
|
||||
with Go 1.0 and newer.
|
||||
|
||||
## Documentation
|
||||
|
||||
https://godoc.org/gopkg.in/alexcesaro/quotedprintable.v3
|
24
vendor/gopkg.in/asn1-ber.v1/README.md
generated
vendored
24
vendor/gopkg.in/asn1-ber.v1/README.md
generated
vendored
|
@ -1,24 +0,0 @@
|
|||
[](https://godoc.org/gopkg.in/asn1-ber.v1) [](https://travis-ci.org/go-asn1-ber/asn1-ber)
|
||||
|
||||
|
||||
ASN1 BER Encoding / Decoding Library for the GO programming language.
|
||||
---------------------------------------------------------------------
|
||||
|
||||
Required libraries:
|
||||
None
|
||||
|
||||
Working:
|
||||
Very basic encoding / decoding needed for LDAP protocol
|
||||
|
||||
Tests Implemented:
|
||||
A few
|
||||
|
||||
TODO:
|
||||
Fix all encoding / decoding to conform to ASN1 BER spec
|
||||
Implement Tests / Benchmarks
|
||||
|
||||
---
|
||||
|
||||
The Go gopher was designed by Renee French. (http://reneefrench.blogspot.com/)
|
||||
The design is licensed under the Creative Commons 3.0 Attributions license.
|
||||
Read this article for more details: http://blog.golang.org/gopher
|
2
vendor/gopkg.in/bufio.v1/Makefile
generated
vendored
2
vendor/gopkg.in/bufio.v1/Makefile
generated
vendored
|
@ -1,2 +0,0 @@
|
|||
all:
|
||||
go test gopkg.in/bufio.v1
|
4
vendor/gopkg.in/bufio.v1/README.md
generated
vendored
4
vendor/gopkg.in/bufio.v1/README.md
generated
vendored
|
@ -1,4 +0,0 @@
|
|||
bufio
|
||||
=====
|
||||
|
||||
This is a fork of the http://golang.org/pkg/bufio/ package. It adds `ReadN` method that allows reading next `n` bytes from the internal buffer without allocating intermediate buffer. This method works just like the [Buffer.Next](http://golang.org/pkg/bytes/#Buffer.Next) method, but has slightly different signature.
|
121
vendor/gopkg.in/editorconfig/editorconfig-core-go.v1/README.md
generated
vendored
121
vendor/gopkg.in/editorconfig/editorconfig-core-go.v1/README.md
generated
vendored
|
@ -1,121 +0,0 @@
|
|||
[](https://godoc.org/gopkg.in/editorconfig/editorconfig-core-go.v1)
|
||||
[](https://goreportcard.com/report/gopkg.in/editorconfig/editorconfig-core-go.v1)
|
||||
|
||||
# Editorconfig Core Go
|
||||
|
||||
A [Editorconfig][editorconfig] file parser and manipulator for Go.
|
||||
|
||||
> This package is already working, but still under testing.
|
||||
|
||||
## Installing
|
||||
|
||||
We recommend the use of [gopkg.in][gopkg] for this package:
|
||||
|
||||
```bash
|
||||
go get -u gopkg.in/editorconfig/editorconfig-core-go.v1
|
||||
```
|
||||
|
||||
Import by the same path. Tha package name you will use to access it is
|
||||
`editorconfig`.
|
||||
|
||||
```go
|
||||
import (
|
||||
"gopkg.in/editorconfig/editorconfig-core-go.v1"
|
||||
)
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
### Parse from file
|
||||
|
||||
```go
|
||||
editorConfig, err := editorconfig.ParseFile("path/to/.editorconfig")
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
```
|
||||
|
||||
### Parse from slice of bytes
|
||||
|
||||
```go
|
||||
data := []byte("...")
|
||||
editorConfig, err := editorconfig.ParseBytes(data)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
```
|
||||
|
||||
### Get definition to a given filename
|
||||
|
||||
This method builds a definition to a given filename.
|
||||
This definition is a merge of the properties with selectors that matched the
|
||||
given filename.
|
||||
The lasts sections of the file have preference over the priors.
|
||||
|
||||
```go
|
||||
def := editorConfig.GetDefinitionForFilename("my/file.go")
|
||||
```
|
||||
|
||||
This definition have the following properties:
|
||||
|
||||
```go
|
||||
type Definition struct {
|
||||
Selector string
|
||||
|
||||
Charset string
|
||||
IndentStyle string
|
||||
IndentSize string
|
||||
TabWidth int
|
||||
EndOfLine string
|
||||
TrimTrailingWhitespace bool
|
||||
InsertFinalNewline bool
|
||||
}
|
||||
```
|
||||
|
||||
#### Automatic search for `.editorconfig` files
|
||||
|
||||
If you want a definition of a file without having to manually
|
||||
parse the `.editorconfig` files, you can then use the static version
|
||||
of `GetDefinitionForFilename`:
|
||||
|
||||
```go
|
||||
def, err := editorconfig.GetDefinitionForFilename("foo/bar/baz/my-file.go")
|
||||
```
|
||||
|
||||
In the example above, the package will automatically search for
|
||||
`.editorconfig` files on:
|
||||
|
||||
- `foo/bar/baz/.editorconfig`
|
||||
- `foo/baz/.editorconfig`
|
||||
- `foo/.editorconfig`
|
||||
|
||||
Until it reaches a file with `root = true` or the root of the filesystem.
|
||||
|
||||
### Generating a .editorconfig file
|
||||
|
||||
You can easily convert a Editorconfig struct to a compatible INI file:
|
||||
|
||||
```go
|
||||
// serialize to slice of bytes
|
||||
data, err := editorConfig.Serialize()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
// save directly to file
|
||||
err := editorConfig.Save("path/to/.editorconfig")
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
```
|
||||
|
||||
## Contributing
|
||||
|
||||
To run the tests:
|
||||
|
||||
```bash
|
||||
go test -v
|
||||
```
|
||||
|
||||
[editorconfig]: http://editorconfig.org/
|
||||
[gopkg]: https://gopkg.in
|
20
vendor/gopkg.in/gomail.v2/CHANGELOG.md
generated
vendored
20
vendor/gopkg.in/gomail.v2/CHANGELOG.md
generated
vendored
|
@ -1,20 +0,0 @@
|
|||
# Change Log
|
||||
All notable changes to this project will be documented in this file.
|
||||
This project adheres to [Semantic Versioning](http://semver.org/).
|
||||
|
||||
## [2.0.0] - 2015-09-02
|
||||
|
||||
- Mailer has been removed. It has been replaced by Dialer and Sender.
|
||||
- `File` type and the `CreateFile` and `OpenFile` functions have been removed.
|
||||
- `Message.Attach` and `Message.Embed` have a new signature.
|
||||
- `Message.GetBodyWriter` has been removed. Use `Message.AddAlternativeWriter`
|
||||
instead.
|
||||
- `Message.Export` has been removed. `Message.WriteTo` can be used instead.
|
||||
- `Message.DelHeader` has been removed.
|
||||
- The `Bcc` header field is no longer sent. It is far more simpler and
|
||||
efficient: the same message is sent to all recipients instead of sending a
|
||||
different email to each Bcc address.
|
||||
- LoginAuth has been removed. `NewPlainDialer` now implements the LOGIN
|
||||
authentication mechanism when needed.
|
||||
- Go 1.2 is now required instead of Go 1.3. No external dependency are used when
|
||||
using Go 1.5.
|
20
vendor/gopkg.in/gomail.v2/CONTRIBUTING.md
generated
vendored
20
vendor/gopkg.in/gomail.v2/CONTRIBUTING.md
generated
vendored
|
@ -1,20 +0,0 @@
|
|||
Thank you for contributing to Gomail! Here are a few guidelines:
|
||||
|
||||
## Bugs
|
||||
|
||||
If you think you found a bug, create an issue and supply the minimum amount
|
||||
of code triggering the bug so it can be reproduced.
|
||||
|
||||
|
||||
## Fixing a bug
|
||||
|
||||
If you want to fix a bug, you can send a pull request. It should contains a
|
||||
new test or update an existing one to cover that bug.
|
||||
|
||||
|
||||
## New feature proposal
|
||||
|
||||
If you think Gomail lacks a feature, you can open an issue or send a pull
|
||||
request. I want to keep Gomail code and API as simple as possible so please
|
||||
describe your needs so we can discuss whether this feature should be added to
|
||||
Gomail or not.
|
92
vendor/gopkg.in/gomail.v2/README.md
generated
vendored
92
vendor/gopkg.in/gomail.v2/README.md
generated
vendored
|
@ -1,92 +0,0 @@
|
|||
# Gomail
|
||||
[](https://travis-ci.org/go-gomail/gomail) [](http://gocover.io/gopkg.in/gomail.v2) [](https://godoc.org/gopkg.in/gomail.v2)
|
||||
|
||||
## Introduction
|
||||
|
||||
Gomail is a simple and efficient package to send emails. It is well tested and
|
||||
documented.
|
||||
|
||||
Gomail can only send emails using an SMTP server. But the API is flexible and it
|
||||
is easy to implement other methods for sending emails using a local Postfix, an
|
||||
API, etc.
|
||||
|
||||
It is versioned using [gopkg.in](https://gopkg.in) so I promise
|
||||
there will never be backward incompatible changes within each version.
|
||||
|
||||
It requires Go 1.2 or newer. With Go 1.5, no external dependencies are used.
|
||||
|
||||
|
||||
## Features
|
||||
|
||||
Gomail supports:
|
||||
- Attachments
|
||||
- Embedded images
|
||||
- HTML and text templates
|
||||
- Automatic encoding of special characters
|
||||
- SSL and TLS
|
||||
- Sending multiple emails with the same SMTP connection
|
||||
|
||||
|
||||
## Documentation
|
||||
|
||||
https://godoc.org/gopkg.in/gomail.v2
|
||||
|
||||
|
||||
## Download
|
||||
|
||||
go get gopkg.in/gomail.v2
|
||||
|
||||
|
||||
## Examples
|
||||
|
||||
See the [examples in the documentation](https://godoc.org/gopkg.in/gomail.v2#example-package).
|
||||
|
||||
|
||||
## FAQ
|
||||
|
||||
### x509: certificate signed by unknown authority
|
||||
|
||||
If you get this error it means the certificate used by the SMTP server is not
|
||||
considered valid by the client running Gomail. As a quick workaround you can
|
||||
bypass the verification of the server's certificate chain and host name by using
|
||||
`SetTLSConfig`:
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
|
||||
"gopkg.in/gomail.v2"
|
||||
)
|
||||
|
||||
func main() {
|
||||
d := gomail.NewDialer("smtp.example.com", 587, "user", "123456")
|
||||
d.TLSConfig = &tls.Config{InsecureSkipVerify: true}
|
||||
|
||||
// Send emails using d.
|
||||
}
|
||||
|
||||
Note, however, that this is insecure and should not be used in production.
|
||||
|
||||
|
||||
## Contribute
|
||||
|
||||
Contributions are more than welcome! See [CONTRIBUTING.md](CONTRIBUTING.md) for
|
||||
more info.
|
||||
|
||||
|
||||
## Change log
|
||||
|
||||
See [CHANGELOG.md](CHANGELOG.md).
|
||||
|
||||
|
||||
## License
|
||||
|
||||
[MIT](LICENSE)
|
||||
|
||||
|
||||
## Contact
|
||||
|
||||
You can ask questions on the [Gomail
|
||||
thread](https://groups.google.com/d/topic/golang-nuts/jMxZHzvvEVg/discussion)
|
||||
in the Go mailing-list.
|
15
vendor/gopkg.in/ini.v1/Makefile
generated
vendored
15
vendor/gopkg.in/ini.v1/Makefile
generated
vendored
|
@ -1,15 +0,0 @@
|
|||
.PHONY: build test bench vet coverage
|
||||
|
||||
build: vet bench
|
||||
|
||||
test:
|
||||
go test -v -cover -race
|
||||
|
||||
bench:
|
||||
go test -v -cover -race -test.bench=. -test.benchmem
|
||||
|
||||
vet:
|
||||
go vet
|
||||
|
||||
coverage:
|
||||
go test -coverprofile=c.out && go tool cover -html=c.out && rm c.out
|
763
vendor/gopkg.in/ini.v1/README.md
generated
vendored
763
vendor/gopkg.in/ini.v1/README.md
generated
vendored
|
@ -1,763 +0,0 @@
|
|||
INI [](https://travis-ci.org/go-ini/ini) [](https://sourcegraph.com/github.com/go-ini/ini?badge)
|
||||
===
|
||||
|
||||

|
||||
|
||||
Package ini provides INI file read and write functionality in Go.
|
||||
|
||||
[简体中文](README_ZH.md)
|
||||
|
||||
## Feature
|
||||
|
||||
- Load multiple data sources(`[]byte`, file and `io.ReadCloser`) with overwrites.
|
||||
- Read with recursion values.
|
||||
- Read with parent-child sections.
|
||||
- Read with auto-increment key names.
|
||||
- Read with multiple-line values.
|
||||
- Read with tons of helper methods.
|
||||
- Read and convert values to Go types.
|
||||
- Read and **WRITE** comments of sections and keys.
|
||||
- Manipulate sections, keys and comments with ease.
|
||||
- Keep sections and keys in order as you parse and save.
|
||||
|
||||
## Installation
|
||||
|
||||
To use a tagged revision:
|
||||
|
||||
go get gopkg.in/ini.v1
|
||||
|
||||
To use with latest changes:
|
||||
|
||||
go get github.com/go-ini/ini
|
||||
|
||||
Please add `-u` flag to update in the future.
|
||||
|
||||
### Testing
|
||||
|
||||
If you want to test on your machine, please apply `-t` flag:
|
||||
|
||||
go get -t gopkg.in/ini.v1
|
||||
|
||||
Please add `-u` flag to update in the future.
|
||||
|
||||
## Getting Started
|
||||
|
||||
### Loading from data sources
|
||||
|
||||
A **Data Source** is either raw data in type `[]byte`, a file name with type `string` or `io.ReadCloser`. You can load **as many data sources as you want**. Passing other types will simply return an error.
|
||||
|
||||
```go
|
||||
cfg, err := ini.Load([]byte("raw data"), "filename", ioutil.NopCloser(bytes.NewReader([]byte("some other data"))))
|
||||
```
|
||||
|
||||
Or start with an empty object:
|
||||
|
||||
```go
|
||||
cfg := ini.Empty()
|
||||
```
|
||||
|
||||
When you cannot decide how many data sources to load at the beginning, you will still be able to **Append()** them later.
|
||||
|
||||
```go
|
||||
err := cfg.Append("other file", []byte("other raw data"))
|
||||
```
|
||||
|
||||
If you have a list of files with possibilities that some of them may not available at the time, and you don't know exactly which ones, you can use `LooseLoad` to ignore nonexistent files without returning error.
|
||||
|
||||
```go
|
||||
cfg, err := ini.LooseLoad("filename", "filename_404")
|
||||
```
|
||||
|
||||
The cool thing is, whenever the file is available to load while you're calling `Reload` method, it will be counted as usual.
|
||||
|
||||
#### Ignore cases of key name
|
||||
|
||||
When you do not care about cases of section and key names, you can use `InsensitiveLoad` to force all names to be lowercased while parsing.
|
||||
|
||||
```go
|
||||
cfg, err := ini.InsensitiveLoad("filename")
|
||||
//...
|
||||
|
||||
// sec1 and sec2 are the exactly same section object
|
||||
sec1, err := cfg.GetSection("Section")
|
||||
sec2, err := cfg.GetSection("SecTIOn")
|
||||
|
||||
// key1 and key2 are the exactly same key object
|
||||
key1, err := sec1.GetKey("Key")
|
||||
key2, err := sec2.GetKey("KeY")
|
||||
```
|
||||
|
||||
#### MySQL-like boolean key
|
||||
|
||||
MySQL's configuration allows a key without value as follows:
|
||||
|
||||
```ini
|
||||
[mysqld]
|
||||
...
|
||||
skip-host-cache
|
||||
skip-name-resolve
|
||||
```
|
||||
|
||||
By default, this is considered as missing value. But if you know you're going to deal with those cases, you can assign advanced load options:
|
||||
|
||||
```go
|
||||
cfg, err := ini.LoadSources(ini.LoadOptions{AllowBooleanKeys: true}, "my.cnf"))
|
||||
```
|
||||
|
||||
The value of those keys are always `true`, and when you save to a file, it will keep in the same foramt as you read.
|
||||
|
||||
To generate such keys in your program, you could use `NewBooleanKey`:
|
||||
|
||||
```go
|
||||
key, err := sec.NewBooleanKey("skip-host-cache")
|
||||
```
|
||||
|
||||
#### Comment
|
||||
|
||||
Take care that following format will be treated as comment:
|
||||
|
||||
1. Line begins with `#` or `;`
|
||||
2. Words after `#` or `;`
|
||||
3. Words after section name (i.e words after `[some section name]`)
|
||||
|
||||
If you want to save a value with `#` or `;`, please quote them with ``` ` ``` or ``` """ ```.
|
||||
|
||||
Alternatively, you can use following `LoadOptions` to completely ignore inline comments:
|
||||
|
||||
```go
|
||||
cfg, err := ini.LoadSources(ini.LoadOptions{IgnoreInlineComment: true}, "app.ini"))
|
||||
```
|
||||
|
||||
### Working with sections
|
||||
|
||||
To get a section, you would need to:
|
||||
|
||||
```go
|
||||
section, err := cfg.GetSection("section name")
|
||||
```
|
||||
|
||||
For a shortcut for default section, just give an empty string as name:
|
||||
|
||||
```go
|
||||
section, err := cfg.GetSection("")
|
||||
```
|
||||
|
||||
When you're pretty sure the section exists, following code could make your life easier:
|
||||
|
||||
```go
|
||||
section := cfg.Section("section name")
|
||||
```
|
||||
|
||||
What happens when the section somehow does not exist? Don't panic, it automatically creates and returns a new section to you.
|
||||
|
||||
To create a new section:
|
||||
|
||||
```go
|
||||
err := cfg.NewSection("new section")
|
||||
```
|
||||
|
||||
To get a list of sections or section names:
|
||||
|
||||
```go
|
||||
sections := cfg.Sections()
|
||||
names := cfg.SectionStrings()
|
||||
```
|
||||
|
||||
### Working with keys
|
||||
|
||||
To get a key under a section:
|
||||
|
||||
```go
|
||||
key, err := cfg.Section("").GetKey("key name")
|
||||
```
|
||||
|
||||
Same rule applies to key operations:
|
||||
|
||||
```go
|
||||
key := cfg.Section("").Key("key name")
|
||||
```
|
||||
|
||||
To check if a key exists:
|
||||
|
||||
```go
|
||||
yes := cfg.Section("").HasKey("key name")
|
||||
```
|
||||
|
||||
To create a new key:
|
||||
|
||||
```go
|
||||
err := cfg.Section("").NewKey("name", "value")
|
||||
```
|
||||
|
||||
To get a list of keys or key names:
|
||||
|
||||
```go
|
||||
keys := cfg.Section("").Keys()
|
||||
names := cfg.Section("").KeyStrings()
|
||||
```
|
||||
|
||||
To get a clone hash of keys and corresponding values:
|
||||
|
||||
```go
|
||||
hash := cfg.Section("").KeysHash()
|
||||
```
|
||||
|
||||
### Working with values
|
||||
|
||||
To get a string value:
|
||||
|
||||
```go
|
||||
val := cfg.Section("").Key("key name").String()
|
||||
```
|
||||
|
||||
To validate key value on the fly:
|
||||
|
||||
```go
|
||||
val := cfg.Section("").Key("key name").Validate(func(in string) string {
|
||||
if len(in) == 0 {
|
||||
return "default"
|
||||
}
|
||||
return in
|
||||
})
|
||||
```
|
||||
|
||||
If you do not want any auto-transformation (such as recursive read) for the values, you can get raw value directly (this way you get much better performance):
|
||||
|
||||
```go
|
||||
val := cfg.Section("").Key("key name").Value()
|
||||
```
|
||||
|
||||
To check if raw value exists:
|
||||
|
||||
```go
|
||||
yes := cfg.Section("").HasValue("test value")
|
||||
```
|
||||
|
||||
To get value with types:
|
||||
|
||||
```go
|
||||
// For boolean values:
|
||||
// true when value is: 1, t, T, TRUE, true, True, YES, yes, Yes, y, ON, on, On
|
||||
// false when value is: 0, f, F, FALSE, false, False, NO, no, No, n, OFF, off, Off
|
||||
v, err = cfg.Section("").Key("BOOL").Bool()
|
||||
v, err = cfg.Section("").Key("FLOAT64").Float64()
|
||||
v, err = cfg.Section("").Key("INT").Int()
|
||||
v, err = cfg.Section("").Key("INT64").Int64()
|
||||
v, err = cfg.Section("").Key("UINT").Uint()
|
||||
v, err = cfg.Section("").Key("UINT64").Uint64()
|
||||
v, err = cfg.Section("").Key("TIME").TimeFormat(time.RFC3339)
|
||||
v, err = cfg.Section("").Key("TIME").Time() // RFC3339
|
||||
|
||||
v = cfg.Section("").Key("BOOL").MustBool()
|
||||
v = cfg.Section("").Key("FLOAT64").MustFloat64()
|
||||
v = cfg.Section("").Key("INT").MustInt()
|
||||
v = cfg.Section("").Key("INT64").MustInt64()
|
||||
v = cfg.Section("").Key("UINT").MustUint()
|
||||
v = cfg.Section("").Key("UINT64").MustUint64()
|
||||
v = cfg.Section("").Key("TIME").MustTimeFormat(time.RFC3339)
|
||||
v = cfg.Section("").Key("TIME").MustTime() // RFC3339
|
||||
|
||||
// Methods start with Must also accept one argument for default value
|
||||
// when key not found or fail to parse value to given type.
|
||||
// Except method MustString, which you have to pass a default value.
|
||||
|
||||
v = cfg.Section("").Key("String").MustString("default")
|
||||
v = cfg.Section("").Key("BOOL").MustBool(true)
|
||||
v = cfg.Section("").Key("FLOAT64").MustFloat64(1.25)
|
||||
v = cfg.Section("").Key("INT").MustInt(10)
|
||||
v = cfg.Section("").Key("INT64").MustInt64(99)
|
||||
v = cfg.Section("").Key("UINT").MustUint(3)
|
||||
v = cfg.Section("").Key("UINT64").MustUint64(6)
|
||||
v = cfg.Section("").Key("TIME").MustTimeFormat(time.RFC3339, time.Now())
|
||||
v = cfg.Section("").Key("TIME").MustTime(time.Now()) // RFC3339
|
||||
```
|
||||
|
||||
What if my value is three-line long?
|
||||
|
||||
```ini
|
||||
[advance]
|
||||
ADDRESS = """404 road,
|
||||
NotFound, State, 5000
|
||||
Earth"""
|
||||
```
|
||||
|
||||
Not a problem!
|
||||
|
||||
```go
|
||||
cfg.Section("advance").Key("ADDRESS").String()
|
||||
|
||||
/* --- start ---
|
||||
404 road,
|
||||
NotFound, State, 5000
|
||||
Earth
|
||||
------ end --- */
|
||||
```
|
||||
|
||||
That's cool, how about continuation lines?
|
||||
|
||||
```ini
|
||||
[advance]
|
||||
two_lines = how about \
|
||||
continuation lines?
|
||||
lots_of_lines = 1 \
|
||||
2 \
|
||||
3 \
|
||||
4
|
||||
```
|
||||
|
||||
Piece of cake!
|
||||
|
||||
```go
|
||||
cfg.Section("advance").Key("two_lines").String() // how about continuation lines?
|
||||
cfg.Section("advance").Key("lots_of_lines").String() // 1 2 3 4
|
||||
```
|
||||
|
||||
Well, I hate continuation lines, how do I disable that?
|
||||
|
||||
```go
|
||||
cfg, err := ini.LoadSources(ini.LoadOptions{
|
||||
IgnoreContinuation: true,
|
||||
}, "filename")
|
||||
```
|
||||
|
||||
Holy crap!
|
||||
|
||||
Note that single quotes around values will be stripped:
|
||||
|
||||
```ini
|
||||
foo = "some value" // foo: some value
|
||||
bar = 'some value' // bar: some value
|
||||
```
|
||||
|
||||
Sometimes you downloaded file from [Crowdin](https://crowdin.com/) has values like the following (value is surrounded by double quotes and quotes in the value are escaped):
|
||||
|
||||
```ini
|
||||
create_repo="created repository <a href=\"%s\">%s</a>"
|
||||
```
|
||||
|
||||
How do you transform this to regular format automatically?
|
||||
|
||||
```go
|
||||
cfg, err := ini.LoadSources(ini.LoadOptions{UnescapeValueDoubleQuotes: true}, "en-US.ini"))
|
||||
cfg.Section("<name of your section>").Key("create_repo").String()
|
||||
// You got: created repository <a href="%s">%s</a>
|
||||
```
|
||||
|
||||
That's all? Hmm, no.
|
||||
|
||||
#### Helper methods of working with values
|
||||
|
||||
To get value with given candidates:
|
||||
|
||||
```go
|
||||
v = cfg.Section("").Key("STRING").In("default", []string{"str", "arr", "types"})
|
||||
v = cfg.Section("").Key("FLOAT64").InFloat64(1.1, []float64{1.25, 2.5, 3.75})
|
||||
v = cfg.Section("").Key("INT").InInt(5, []int{10, 20, 30})
|
||||
v = cfg.Section("").Key("INT64").InInt64(10, []int64{10, 20, 30})
|
||||
v = cfg.Section("").Key("UINT").InUint(4, []int{3, 6, 9})
|
||||
v = cfg.Section("").Key("UINT64").InUint64(8, []int64{3, 6, 9})
|
||||
v = cfg.Section("").Key("TIME").InTimeFormat(time.RFC3339, time.Now(), []time.Time{time1, time2, time3})
|
||||
v = cfg.Section("").Key("TIME").InTime(time.Now(), []time.Time{time1, time2, time3}) // RFC3339
|
||||
```
|
||||
|
||||
Default value will be presented if value of key is not in candidates you given, and default value does not need be one of candidates.
|
||||
|
||||
To validate value in a given range:
|
||||
|
||||
```go
|
||||
vals = cfg.Section("").Key("FLOAT64").RangeFloat64(0.0, 1.1, 2.2)
|
||||
vals = cfg.Section("").Key("INT").RangeInt(0, 10, 20)
|
||||
vals = cfg.Section("").Key("INT64").RangeInt64(0, 10, 20)
|
||||
vals = cfg.Section("").Key("UINT").RangeUint(0, 3, 9)
|
||||
vals = cfg.Section("").Key("UINT64").RangeUint64(0, 3, 9)
|
||||
vals = cfg.Section("").Key("TIME").RangeTimeFormat(time.RFC3339, time.Now(), minTime, maxTime)
|
||||
vals = cfg.Section("").Key("TIME").RangeTime(time.Now(), minTime, maxTime) // RFC3339
|
||||
```
|
||||
|
||||
##### Auto-split values into a slice
|
||||
|
||||
To use zero value of type for invalid inputs:
|
||||
|
||||
```go
|
||||
// Input: 1.1, 2.2, 3.3, 4.4 -> [1.1 2.2 3.3 4.4]
|
||||
// Input: how, 2.2, are, you -> [0.0 2.2 0.0 0.0]
|
||||
vals = cfg.Section("").Key("STRINGS").Strings(",")
|
||||
vals = cfg.Section("").Key("FLOAT64S").Float64s(",")
|
||||
vals = cfg.Section("").Key("INTS").Ints(",")
|
||||
vals = cfg.Section("").Key("INT64S").Int64s(",")
|
||||
vals = cfg.Section("").Key("UINTS").Uints(",")
|
||||
vals = cfg.Section("").Key("UINT64S").Uint64s(",")
|
||||
vals = cfg.Section("").Key("TIMES").Times(",")
|
||||
```
|
||||
|
||||
To exclude invalid values out of result slice:
|
||||
|
||||
```go
|
||||
// Input: 1.1, 2.2, 3.3, 4.4 -> [1.1 2.2 3.3 4.4]
|
||||
// Input: how, 2.2, are, you -> [2.2]
|
||||
vals = cfg.Section("").Key("FLOAT64S").ValidFloat64s(",")
|
||||
vals = cfg.Section("").Key("INTS").ValidInts(",")
|
||||
vals = cfg.Section("").Key("INT64S").ValidInt64s(",")
|
||||
vals = cfg.Section("").Key("UINTS").ValidUints(",")
|
||||
vals = cfg.Section("").Key("UINT64S").ValidUint64s(",")
|
||||
vals = cfg.Section("").Key("TIMES").ValidTimes(",")
|
||||
```
|
||||
|
||||
Or to return nothing but error when have invalid inputs:
|
||||
|
||||
```go
|
||||
// Input: 1.1, 2.2, 3.3, 4.4 -> [1.1 2.2 3.3 4.4]
|
||||
// Input: how, 2.2, are, you -> error
|
||||
vals = cfg.Section("").Key("FLOAT64S").StrictFloat64s(",")
|
||||
vals = cfg.Section("").Key("INTS").StrictInts(",")
|
||||
vals = cfg.Section("").Key("INT64S").StrictInt64s(",")
|
||||
vals = cfg.Section("").Key("UINTS").StrictUints(",")
|
||||
vals = cfg.Section("").Key("UINT64S").StrictUint64s(",")
|
||||
vals = cfg.Section("").Key("TIMES").StrictTimes(",")
|
||||
```
|
||||
|
||||
### Save your configuration
|
||||
|
||||
Finally, it's time to save your configuration to somewhere.
|
||||
|
||||
A typical way to save configuration is writing it to a file:
|
||||
|
||||
```go
|
||||
// ...
|
||||
err = cfg.SaveTo("my.ini")
|
||||
err = cfg.SaveToIndent("my.ini", "\t")
|
||||
```
|
||||
|
||||
Another way to save is writing to a `io.Writer` interface:
|
||||
|
||||
```go
|
||||
// ...
|
||||
cfg.WriteTo(writer)
|
||||
cfg.WriteToIndent(writer, "\t")
|
||||
```
|
||||
|
||||
By default, spaces are used to align "=" sign between key and values, to disable that:
|
||||
|
||||
```go
|
||||
ini.PrettyFormat = false
|
||||
```
|
||||
|
||||
## Advanced Usage
|
||||
|
||||
### Recursive Values
|
||||
|
||||
For all value of keys, there is a special syntax `%(<name>)s`, where `<name>` is the key name in same section or default section, and `%(<name>)s` will be replaced by corresponding value(empty string if key not found). You can use this syntax at most 99 level of recursions.
|
||||
|
||||
```ini
|
||||
NAME = ini
|
||||
|
||||
[author]
|
||||
NAME = Unknwon
|
||||
GITHUB = https://github.com/%(NAME)s
|
||||
|
||||
[package]
|
||||
FULL_NAME = github.com/go-ini/%(NAME)s
|
||||
```
|
||||
|
||||
```go
|
||||
cfg.Section("author").Key("GITHUB").String() // https://github.com/Unknwon
|
||||
cfg.Section("package").Key("FULL_NAME").String() // github.com/go-ini/ini
|
||||
```
|
||||
|
||||
### Parent-child Sections
|
||||
|
||||
You can use `.` in section name to indicate parent-child relationship between two or more sections. If the key not found in the child section, library will try again on its parent section until there is no parent section.
|
||||
|
||||
```ini
|
||||
NAME = ini
|
||||
VERSION = v1
|
||||
IMPORT_PATH = gopkg.in/%(NAME)s.%(VERSION)s
|
||||
|
||||
[package]
|
||||
CLONE_URL = https://%(IMPORT_PATH)s
|
||||
|
||||
[package.sub]
|
||||
```
|
||||
|
||||
```go
|
||||
cfg.Section("package.sub").Key("CLONE_URL").String() // https://gopkg.in/ini.v1
|
||||
```
|
||||
|
||||
#### Retrieve parent keys available to a child section
|
||||
|
||||
```go
|
||||
cfg.Section("package.sub").ParentKeys() // ["CLONE_URL"]
|
||||
```
|
||||
|
||||
### Unparseable Sections
|
||||
|
||||
Sometimes, you have sections that do not contain key-value pairs but raw content, to handle such case, you can use `LoadOptions.UnparsableSections`:
|
||||
|
||||
```go
|
||||
cfg, err := ini.LoadSources(ini.LoadOptions{UnparseableSections: []string{"COMMENTS"}}, `[COMMENTS]
|
||||
<1><L.Slide#2> This slide has the fuel listed in the wrong units <e.1>`))
|
||||
|
||||
body := cfg.Section("COMMENTS").Body()
|
||||
|
||||
/* --- start ---
|
||||
<1><L.Slide#2> This slide has the fuel listed in the wrong units <e.1>
|
||||
------ end --- */
|
||||
```
|
||||
|
||||
### Auto-increment Key Names
|
||||
|
||||
If key name is `-` in data source, then it would be seen as special syntax for auto-increment key name start from 1, and every section is independent on counter.
|
||||
|
||||
```ini
|
||||
[features]
|
||||
-: Support read/write comments of keys and sections
|
||||
-: Support auto-increment of key names
|
||||
-: Support load multiple files to overwrite key values
|
||||
```
|
||||
|
||||
```go
|
||||
cfg.Section("features").KeyStrings() // []{"#1", "#2", "#3"}
|
||||
```
|
||||
|
||||
### Map To Struct
|
||||
|
||||
Want more objective way to play with INI? Cool.
|
||||
|
||||
```ini
|
||||
Name = Unknwon
|
||||
age = 21
|
||||
Male = true
|
||||
Born = 1993-01-01T20:17:05Z
|
||||
|
||||
[Note]
|
||||
Content = Hi is a good man!
|
||||
Cities = HangZhou, Boston
|
||||
```
|
||||
|
||||
```go
|
||||
type Note struct {
|
||||
Content string
|
||||
Cities []string
|
||||
}
|
||||
|
||||
type Person struct {
|
||||
Name string
|
||||
Age int `ini:"age"`
|
||||
Male bool
|
||||
Born time.Time
|
||||
Note
|
||||
Created time.Time `ini:"-"`
|
||||
}
|
||||
|
||||
func main() {
|
||||
cfg, err := ini.Load("path/to/ini")
|
||||
// ...
|
||||
p := new(Person)
|
||||
err = cfg.MapTo(p)
|
||||
// ...
|
||||
|
||||
// Things can be simpler.
|
||||
err = ini.MapTo(p, "path/to/ini")
|
||||
// ...
|
||||
|
||||
// Just map a section? Fine.
|
||||
n := new(Note)
|
||||
err = cfg.Section("Note").MapTo(n)
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
Can I have default value for field? Absolutely.
|
||||
|
||||
Assign it before you map to struct. It will keep the value as it is if the key is not presented or got wrong type.
|
||||
|
||||
```go
|
||||
// ...
|
||||
p := &Person{
|
||||
Name: "Joe",
|
||||
}
|
||||
// ...
|
||||
```
|
||||
|
||||
It's really cool, but what's the point if you can't give me my file back from struct?
|
||||
|
||||
### Reflect From Struct
|
||||
|
||||
Why not?
|
||||
|
||||
```go
|
||||
type Embeded struct {
|
||||
Dates []time.Time `delim:"|" comment:"Time data"`
|
||||
Places []string `ini:"places,omitempty"`
|
||||
None []int `ini:",omitempty"`
|
||||
}
|
||||
|
||||
type Author struct {
|
||||
Name string `ini:"NAME"`
|
||||
Male bool
|
||||
Age int `comment:"Author's age"`
|
||||
GPA float64
|
||||
NeverMind string `ini:"-"`
|
||||
*Embeded `comment:"Embeded section"`
|
||||
}
|
||||
|
||||
func main() {
|
||||
a := &Author{"Unknwon", true, 21, 2.8, "",
|
||||
&Embeded{
|
||||
[]time.Time{time.Now(), time.Now()},
|
||||
[]string{"HangZhou", "Boston"},
|
||||
[]int{},
|
||||
}}
|
||||
cfg := ini.Empty()
|
||||
err = ini.ReflectFrom(cfg, a)
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
So, what do I get?
|
||||
|
||||
```ini
|
||||
NAME = Unknwon
|
||||
Male = true
|
||||
; Author's age
|
||||
Age = 21
|
||||
GPA = 2.8
|
||||
|
||||
; Embeded section
|
||||
[Embeded]
|
||||
; Time data
|
||||
Dates = 2015-08-07T22:14:22+08:00|2015-08-07T22:14:22+08:00
|
||||
places = HangZhou,Boston
|
||||
```
|
||||
|
||||
#### Name Mapper
|
||||
|
||||
To save your time and make your code cleaner, this library supports [`NameMapper`](https://gowalker.org/gopkg.in/ini.v1#NameMapper) between struct field and actual section and key name.
|
||||
|
||||
There are 2 built-in name mappers:
|
||||
|
||||
- `AllCapsUnderscore`: it converts to format `ALL_CAPS_UNDERSCORE` then match section or key.
|
||||
- `TitleUnderscore`: it converts to format `title_underscore` then match section or key.
|
||||
|
||||
To use them:
|
||||
|
||||
```go
|
||||
type Info struct {
|
||||
PackageName string
|
||||
}
|
||||
|
||||
func main() {
|
||||
err = ini.MapToWithMapper(&Info{}, ini.TitleUnderscore, []byte("package_name=ini"))
|
||||
// ...
|
||||
|
||||
cfg, err := ini.Load([]byte("PACKAGE_NAME=ini"))
|
||||
// ...
|
||||
info := new(Info)
|
||||
cfg.NameMapper = ini.AllCapsUnderscore
|
||||
err = cfg.MapTo(info)
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
Same rules of name mapper apply to `ini.ReflectFromWithMapper` function.
|
||||
|
||||
#### Value Mapper
|
||||
|
||||
To expand values (e.g. from environment variables), you can use the `ValueMapper` to transform values:
|
||||
|
||||
```go
|
||||
type Env struct {
|
||||
Foo string `ini:"foo"`
|
||||
}
|
||||
|
||||
func main() {
|
||||
cfg, err := ini.Load([]byte("[env]\nfoo = ${MY_VAR}\n")
|
||||
cfg.ValueMapper = os.ExpandEnv
|
||||
// ...
|
||||
env := &Env{}
|
||||
err = cfg.Section("env").MapTo(env)
|
||||
}
|
||||
```
|
||||
|
||||
This would set the value of `env.Foo` to the value of the environment variable `MY_VAR`.
|
||||
|
||||
#### Other Notes On Map/Reflect
|
||||
|
||||
Any embedded struct is treated as a section by default, and there is no automatic parent-child relations in map/reflect feature:
|
||||
|
||||
```go
|
||||
type Child struct {
|
||||
Age string
|
||||
}
|
||||
|
||||
type Parent struct {
|
||||
Name string
|
||||
Child
|
||||
}
|
||||
|
||||
type Config struct {
|
||||
City string
|
||||
Parent
|
||||
}
|
||||
```
|
||||
|
||||
Example configuration:
|
||||
|
||||
```ini
|
||||
City = Boston
|
||||
|
||||
[Parent]
|
||||
Name = Unknwon
|
||||
|
||||
[Child]
|
||||
Age = 21
|
||||
```
|
||||
|
||||
What if, yes, I'm paranoid, I want embedded struct to be in the same section. Well, all roads lead to Rome.
|
||||
|
||||
```go
|
||||
type Child struct {
|
||||
Age string
|
||||
}
|
||||
|
||||
type Parent struct {
|
||||
Name string
|
||||
Child `ini:"Parent"`
|
||||
}
|
||||
|
||||
type Config struct {
|
||||
City string
|
||||
Parent
|
||||
}
|
||||
```
|
||||
|
||||
Example configuration:
|
||||
|
||||
```ini
|
||||
City = Boston
|
||||
|
||||
[Parent]
|
||||
Name = Unknwon
|
||||
Age = 21
|
||||
```
|
||||
|
||||
## Getting Help
|
||||
|
||||
- [API Documentation](https://gowalker.org/gopkg.in/ini.v1)
|
||||
- [File An Issue](https://github.com/go-ini/ini/issues/new)
|
||||
|
||||
## FAQs
|
||||
|
||||
### What does `BlockMode` field do?
|
||||
|
||||
By default, library lets you read and write values so we need a locker to make sure your data is safe. But in cases that you are very sure about only reading data through the library, you can set `cfg.BlockMode = false` to speed up read operations about **50-70%** faster.
|
||||
|
||||
### Why another INI library?
|
||||
|
||||
Many people are using my another INI library [goconfig](https://github.com/Unknwon/goconfig), so the reason for this one is I would like to make more Go style code. Also when you set `cfg.BlockMode = false`, this one is about **10-30%** faster.
|
||||
|
||||
To make those changes I have to confirm API broken, so it's safer to keep it in another place and start using `gopkg.in` to version my package at this time.(PS: shorter import path)
|
||||
|
||||
## License
|
||||
|
||||
This project is under Apache v2 License. See the [LICENSE](LICENSE) file for the full license text.
|
750
vendor/gopkg.in/ini.v1/README_ZH.md
generated
vendored
750
vendor/gopkg.in/ini.v1/README_ZH.md
generated
vendored
|
@ -1,750 +0,0 @@
|
|||
本包提供了 Go 语言中读写 INI 文件的功能。
|
||||
|
||||
## 功能特性
|
||||
|
||||
- 支持覆盖加载多个数据源(`[]byte`、文件和 `io.ReadCloser`)
|
||||
- 支持递归读取键值
|
||||
- 支持读取父子分区
|
||||
- 支持读取自增键名
|
||||
- 支持读取多行的键值
|
||||
- 支持大量辅助方法
|
||||
- 支持在读取时直接转换为 Go 语言类型
|
||||
- 支持读取和 **写入** 分区和键的注释
|
||||
- 轻松操作分区、键值和注释
|
||||
- 在保存文件时分区和键值会保持原有的顺序
|
||||
|
||||
## 下载安装
|
||||
|
||||
使用一个特定版本:
|
||||
|
||||
go get gopkg.in/ini.v1
|
||||
|
||||
使用最新版:
|
||||
|
||||
go get github.com/go-ini/ini
|
||||
|
||||
如需更新请添加 `-u` 选项。
|
||||
|
||||
### 测试安装
|
||||
|
||||
如果您想要在自己的机器上运行测试,请使用 `-t` 标记:
|
||||
|
||||
go get -t gopkg.in/ini.v1
|
||||
|
||||
如需更新请添加 `-u` 选项。
|
||||
|
||||
## 开始使用
|
||||
|
||||
### 从数据源加载
|
||||
|
||||
一个 **数据源** 可以是 `[]byte` 类型的原始数据,`string` 类型的文件路径或 `io.ReadCloser`。您可以加载 **任意多个** 数据源。如果您传递其它类型的数据源,则会直接返回错误。
|
||||
|
||||
```go
|
||||
cfg, err := ini.Load([]byte("raw data"), "filename", ioutil.NopCloser(bytes.NewReader([]byte("some other data"))))
|
||||
```
|
||||
|
||||
或者从一个空白的文件开始:
|
||||
|
||||
```go
|
||||
cfg := ini.Empty()
|
||||
```
|
||||
|
||||
当您在一开始无法决定需要加载哪些数据源时,仍可以使用 **Append()** 在需要的时候加载它们。
|
||||
|
||||
```go
|
||||
err := cfg.Append("other file", []byte("other raw data"))
|
||||
```
|
||||
|
||||
当您想要加载一系列文件,但是不能够确定其中哪些文件是不存在的,可以通过调用函数 `LooseLoad` 来忽略它们(`Load` 会因为文件不存在而返回错误):
|
||||
|
||||
```go
|
||||
cfg, err := ini.LooseLoad("filename", "filename_404")
|
||||
```
|
||||
|
||||
更牛逼的是,当那些之前不存在的文件在重新调用 `Reload` 方法的时候突然出现了,那么它们会被正常加载。
|
||||
|
||||
#### 忽略键名的大小写
|
||||
|
||||
有时候分区和键的名称大小写混合非常烦人,这个时候就可以通过 `InsensitiveLoad` 将所有分区和键名在读取里强制转换为小写:
|
||||
|
||||
```go
|
||||
cfg, err := ini.InsensitiveLoad("filename")
|
||||
//...
|
||||
|
||||
// sec1 和 sec2 指向同一个分区对象
|
||||
sec1, err := cfg.GetSection("Section")
|
||||
sec2, err := cfg.GetSection("SecTIOn")
|
||||
|
||||
// key1 和 key2 指向同一个键对象
|
||||
key1, err := sec1.GetKey("Key")
|
||||
key2, err := sec2.GetKey("KeY")
|
||||
```
|
||||
|
||||
#### 类似 MySQL 配置中的布尔值键
|
||||
|
||||
MySQL 的配置文件中会出现没有具体值的布尔类型的键:
|
||||
|
||||
```ini
|
||||
[mysqld]
|
||||
...
|
||||
skip-host-cache
|
||||
skip-name-resolve
|
||||
```
|
||||
|
||||
默认情况下这被认为是缺失值而无法完成解析,但可以通过高级的加载选项对它们进行处理:
|
||||
|
||||
```go
|
||||
cfg, err := ini.LoadSources(ini.LoadOptions{AllowBooleanKeys: true}, "my.cnf"))
|
||||
```
|
||||
|
||||
这些键的值永远为 `true`,且在保存到文件时也只会输出键名。
|
||||
|
||||
如果您想要通过程序来生成此类键,则可以使用 `NewBooleanKey`:
|
||||
|
||||
```go
|
||||
key, err := sec.NewBooleanKey("skip-host-cache")
|
||||
```
|
||||
|
||||
#### 关于注释
|
||||
|
||||
下述几种情况的内容将被视为注释:
|
||||
|
||||
1. 所有以 `#` 或 `;` 开头的行
|
||||
2. 所有在 `#` 或 `;` 之后的内容
|
||||
3. 分区标签后的文字 (即 `[分区名]` 之后的内容)
|
||||
|
||||
如果你希望使用包含 `#` 或 `;` 的值,请使用 ``` ` ``` 或 ``` """ ``` 进行包覆。
|
||||
|
||||
除此之外,您还可以通过 `LoadOptions` 完全忽略行内注释:
|
||||
|
||||
```go
|
||||
cfg, err := ini.LoadSources(ini.LoadOptions{IgnoreInlineComment: true}, "app.ini"))
|
||||
```
|
||||
|
||||
### 操作分区(Section)
|
||||
|
||||
获取指定分区:
|
||||
|
||||
```go
|
||||
section, err := cfg.GetSection("section name")
|
||||
```
|
||||
|
||||
如果您想要获取默认分区,则可以用空字符串代替分区名:
|
||||
|
||||
```go
|
||||
section, err := cfg.GetSection("")
|
||||
```
|
||||
|
||||
当您非常确定某个分区是存在的,可以使用以下简便方法:
|
||||
|
||||
```go
|
||||
section := cfg.Section("section name")
|
||||
```
|
||||
|
||||
如果不小心判断错了,要获取的分区其实是不存在的,那会发生什么呢?没事的,它会自动创建并返回一个对应的分区对象给您。
|
||||
|
||||
创建一个分区:
|
||||
|
||||
```go
|
||||
err := cfg.NewSection("new section")
|
||||
```
|
||||
|
||||
获取所有分区对象或名称:
|
||||
|
||||
```go
|
||||
sections := cfg.Sections()
|
||||
names := cfg.SectionStrings()
|
||||
```
|
||||
|
||||
### 操作键(Key)
|
||||
|
||||
获取某个分区下的键:
|
||||
|
||||
```go
|
||||
key, err := cfg.Section("").GetKey("key name")
|
||||
```
|
||||
|
||||
和分区一样,您也可以直接获取键而忽略错误处理:
|
||||
|
||||
```go
|
||||
key := cfg.Section("").Key("key name")
|
||||
```
|
||||
|
||||
判断某个键是否存在:
|
||||
|
||||
```go
|
||||
yes := cfg.Section("").HasKey("key name")
|
||||
```
|
||||
|
||||
创建一个新的键:
|
||||
|
||||
```go
|
||||
err := cfg.Section("").NewKey("name", "value")
|
||||
```
|
||||
|
||||
获取分区下的所有键或键名:
|
||||
|
||||
```go
|
||||
keys := cfg.Section("").Keys()
|
||||
names := cfg.Section("").KeyStrings()
|
||||
```
|
||||
|
||||
获取分区下的所有键值对的克隆:
|
||||
|
||||
```go
|
||||
hash := cfg.Section("").KeysHash()
|
||||
```
|
||||
|
||||
### 操作键值(Value)
|
||||
|
||||
获取一个类型为字符串(string)的值:
|
||||
|
||||
```go
|
||||
val := cfg.Section("").Key("key name").String()
|
||||
```
|
||||
|
||||
获取值的同时通过自定义函数进行处理验证:
|
||||
|
||||
```go
|
||||
val := cfg.Section("").Key("key name").Validate(func(in string) string {
|
||||
if len(in) == 0 {
|
||||
return "default"
|
||||
}
|
||||
return in
|
||||
})
|
||||
```
|
||||
|
||||
如果您不需要任何对值的自动转变功能(例如递归读取),可以直接获取原值(这种方式性能最佳):
|
||||
|
||||
```go
|
||||
val := cfg.Section("").Key("key name").Value()
|
||||
```
|
||||
|
||||
判断某个原值是否存在:
|
||||
|
||||
```go
|
||||
yes := cfg.Section("").HasValue("test value")
|
||||
```
|
||||
|
||||
获取其它类型的值:
|
||||
|
||||
```go
|
||||
// 布尔值的规则:
|
||||
// true 当值为:1, t, T, TRUE, true, True, YES, yes, Yes, y, ON, on, On
|
||||
// false 当值为:0, f, F, FALSE, false, False, NO, no, No, n, OFF, off, Off
|
||||
v, err = cfg.Section("").Key("BOOL").Bool()
|
||||
v, err = cfg.Section("").Key("FLOAT64").Float64()
|
||||
v, err = cfg.Section("").Key("INT").Int()
|
||||
v, err = cfg.Section("").Key("INT64").Int64()
|
||||
v, err = cfg.Section("").Key("UINT").Uint()
|
||||
v, err = cfg.Section("").Key("UINT64").Uint64()
|
||||
v, err = cfg.Section("").Key("TIME").TimeFormat(time.RFC3339)
|
||||
v, err = cfg.Section("").Key("TIME").Time() // RFC3339
|
||||
|
||||
v = cfg.Section("").Key("BOOL").MustBool()
|
||||
v = cfg.Section("").Key("FLOAT64").MustFloat64()
|
||||
v = cfg.Section("").Key("INT").MustInt()
|
||||
v = cfg.Section("").Key("INT64").MustInt64()
|
||||
v = cfg.Section("").Key("UINT").MustUint()
|
||||
v = cfg.Section("").Key("UINT64").MustUint64()
|
||||
v = cfg.Section("").Key("TIME").MustTimeFormat(time.RFC3339)
|
||||
v = cfg.Section("").Key("TIME").MustTime() // RFC3339
|
||||
|
||||
// 由 Must 开头的方法名允许接收一个相同类型的参数来作为默认值,
|
||||
// 当键不存在或者转换失败时,则会直接返回该默认值。
|
||||
// 但是,MustString 方法必须传递一个默认值。
|
||||
|
||||
v = cfg.Seciont("").Key("String").MustString("default")
|
||||
v = cfg.Section("").Key("BOOL").MustBool(true)
|
||||
v = cfg.Section("").Key("FLOAT64").MustFloat64(1.25)
|
||||
v = cfg.Section("").Key("INT").MustInt(10)
|
||||
v = cfg.Section("").Key("INT64").MustInt64(99)
|
||||
v = cfg.Section("").Key("UINT").MustUint(3)
|
||||
v = cfg.Section("").Key("UINT64").MustUint64(6)
|
||||
v = cfg.Section("").Key("TIME").MustTimeFormat(time.RFC3339, time.Now())
|
||||
v = cfg.Section("").Key("TIME").MustTime(time.Now()) // RFC3339
|
||||
```
|
||||
|
||||
如果我的值有好多行怎么办?
|
||||
|
||||
```ini
|
||||
[advance]
|
||||
ADDRESS = """404 road,
|
||||
NotFound, State, 5000
|
||||
Earth"""
|
||||
```
|
||||
|
||||
嗯哼?小 case!
|
||||
|
||||
```go
|
||||
cfg.Section("advance").Key("ADDRESS").String()
|
||||
|
||||
/* --- start ---
|
||||
404 road,
|
||||
NotFound, State, 5000
|
||||
Earth
|
||||
------ end --- */
|
||||
```
|
||||
|
||||
赞爆了!那要是我属于一行的内容写不下想要写到第二行怎么办?
|
||||
|
||||
```ini
|
||||
[advance]
|
||||
two_lines = how about \
|
||||
continuation lines?
|
||||
lots_of_lines = 1 \
|
||||
2 \
|
||||
3 \
|
||||
4
|
||||
```
|
||||
|
||||
简直是小菜一碟!
|
||||
|
||||
```go
|
||||
cfg.Section("advance").Key("two_lines").String() // how about continuation lines?
|
||||
cfg.Section("advance").Key("lots_of_lines").String() // 1 2 3 4
|
||||
```
|
||||
|
||||
可是我有时候觉得两行连在一起特别没劲,怎么才能不自动连接两行呢?
|
||||
|
||||
```go
|
||||
cfg, err := ini.LoadSources(ini.LoadOptions{
|
||||
IgnoreContinuation: true,
|
||||
}, "filename")
|
||||
```
|
||||
|
||||
哇靠给力啊!
|
||||
|
||||
需要注意的是,值两侧的单引号会被自动剔除:
|
||||
|
||||
```ini
|
||||
foo = "some value" // foo: some value
|
||||
bar = 'some value' // bar: some value
|
||||
```
|
||||
|
||||
有时您会获得像从 [Crowdin](https://crowdin.com/) 网站下载的文件那样具有特殊格式的值(值使用双引号括起来,内部的双引号被转义):
|
||||
|
||||
```ini
|
||||
create_repo="创建了仓库 <a href=\"%s\">%s</a>"
|
||||
```
|
||||
|
||||
那么,怎么自动地将这类值进行处理呢?
|
||||
|
||||
```go
|
||||
cfg, err := ini.LoadSources(ini.LoadOptions{UnescapeValueDoubleQuotes: true}, "en-US.ini"))
|
||||
cfg.Section("<name of your section>").Key("create_repo").String()
|
||||
// You got: 创建了仓库 <a href="%s">%s</a>
|
||||
```
|
||||
|
||||
这就是全部了?哈哈,当然不是。
|
||||
|
||||
#### 操作键值的辅助方法
|
||||
|
||||
获取键值时设定候选值:
|
||||
|
||||
```go
|
||||
v = cfg.Section("").Key("STRING").In("default", []string{"str", "arr", "types"})
|
||||
v = cfg.Section("").Key("FLOAT64").InFloat64(1.1, []float64{1.25, 2.5, 3.75})
|
||||
v = cfg.Section("").Key("INT").InInt(5, []int{10, 20, 30})
|
||||
v = cfg.Section("").Key("INT64").InInt64(10, []int64{10, 20, 30})
|
||||
v = cfg.Section("").Key("UINT").InUint(4, []int{3, 6, 9})
|
||||
v = cfg.Section("").Key("UINT64").InUint64(8, []int64{3, 6, 9})
|
||||
v = cfg.Section("").Key("TIME").InTimeFormat(time.RFC3339, time.Now(), []time.Time{time1, time2, time3})
|
||||
v = cfg.Section("").Key("TIME").InTime(time.Now(), []time.Time{time1, time2, time3}) // RFC3339
|
||||
```
|
||||
|
||||
如果获取到的值不是候选值的任意一个,则会返回默认值,而默认值不需要是候选值中的一员。
|
||||
|
||||
验证获取的值是否在指定范围内:
|
||||
|
||||
```go
|
||||
vals = cfg.Section("").Key("FLOAT64").RangeFloat64(0.0, 1.1, 2.2)
|
||||
vals = cfg.Section("").Key("INT").RangeInt(0, 10, 20)
|
||||
vals = cfg.Section("").Key("INT64").RangeInt64(0, 10, 20)
|
||||
vals = cfg.Section("").Key("UINT").RangeUint(0, 3, 9)
|
||||
vals = cfg.Section("").Key("UINT64").RangeUint64(0, 3, 9)
|
||||
vals = cfg.Section("").Key("TIME").RangeTimeFormat(time.RFC3339, time.Now(), minTime, maxTime)
|
||||
vals = cfg.Section("").Key("TIME").RangeTime(time.Now(), minTime, maxTime) // RFC3339
|
||||
```
|
||||
|
||||
##### 自动分割键值到切片(slice)
|
||||
|
||||
当存在无效输入时,使用零值代替:
|
||||
|
||||
```go
|
||||
// Input: 1.1, 2.2, 3.3, 4.4 -> [1.1 2.2 3.3 4.4]
|
||||
// Input: how, 2.2, are, you -> [0.0 2.2 0.0 0.0]
|
||||
vals = cfg.Section("").Key("STRINGS").Strings(",")
|
||||
vals = cfg.Section("").Key("FLOAT64S").Float64s(",")
|
||||
vals = cfg.Section("").Key("INTS").Ints(",")
|
||||
vals = cfg.Section("").Key("INT64S").Int64s(",")
|
||||
vals = cfg.Section("").Key("UINTS").Uints(",")
|
||||
vals = cfg.Section("").Key("UINT64S").Uint64s(",")
|
||||
vals = cfg.Section("").Key("TIMES").Times(",")
|
||||
```
|
||||
|
||||
从结果切片中剔除无效输入:
|
||||
|
||||
```go
|
||||
// Input: 1.1, 2.2, 3.3, 4.4 -> [1.1 2.2 3.3 4.4]
|
||||
// Input: how, 2.2, are, you -> [2.2]
|
||||
vals = cfg.Section("").Key("FLOAT64S").ValidFloat64s(",")
|
||||
vals = cfg.Section("").Key("INTS").ValidInts(",")
|
||||
vals = cfg.Section("").Key("INT64S").ValidInt64s(",")
|
||||
vals = cfg.Section("").Key("UINTS").ValidUints(",")
|
||||
vals = cfg.Section("").Key("UINT64S").ValidUint64s(",")
|
||||
vals = cfg.Section("").Key("TIMES").ValidTimes(",")
|
||||
```
|
||||
|
||||
当存在无效输入时,直接返回错误:
|
||||
|
||||
```go
|
||||
// Input: 1.1, 2.2, 3.3, 4.4 -> [1.1 2.2 3.3 4.4]
|
||||
// Input: how, 2.2, are, you -> error
|
||||
vals = cfg.Section("").Key("FLOAT64S").StrictFloat64s(",")
|
||||
vals = cfg.Section("").Key("INTS").StrictInts(",")
|
||||
vals = cfg.Section("").Key("INT64S").StrictInt64s(",")
|
||||
vals = cfg.Section("").Key("UINTS").StrictUints(",")
|
||||
vals = cfg.Section("").Key("UINT64S").StrictUint64s(",")
|
||||
vals = cfg.Section("").Key("TIMES").StrictTimes(",")
|
||||
```
|
||||
|
||||
### 保存配置
|
||||
|
||||
终于到了这个时刻,是时候保存一下配置了。
|
||||
|
||||
比较原始的做法是输出配置到某个文件:
|
||||
|
||||
```go
|
||||
// ...
|
||||
err = cfg.SaveTo("my.ini")
|
||||
err = cfg.SaveToIndent("my.ini", "\t")
|
||||
```
|
||||
|
||||
另一个比较高级的做法是写入到任何实现 `io.Writer` 接口的对象中:
|
||||
|
||||
```go
|
||||
// ...
|
||||
cfg.WriteTo(writer)
|
||||
cfg.WriteToIndent(writer, "\t")
|
||||
```
|
||||
|
||||
默认情况下,空格将被用于对齐键值之间的等号以美化输出结果,以下代码可以禁用该功能:
|
||||
|
||||
```go
|
||||
ini.PrettyFormat = false
|
||||
```
|
||||
|
||||
## 高级用法
|
||||
|
||||
### 递归读取键值
|
||||
|
||||
在获取所有键值的过程中,特殊语法 `%(<name>)s` 会被应用,其中 `<name>` 可以是相同分区或者默认分区下的键名。字符串 `%(<name>)s` 会被相应的键值所替代,如果指定的键不存在,则会用空字符串替代。您可以最多使用 99 层的递归嵌套。
|
||||
|
||||
```ini
|
||||
NAME = ini
|
||||
|
||||
[author]
|
||||
NAME = Unknwon
|
||||
GITHUB = https://github.com/%(NAME)s
|
||||
|
||||
[package]
|
||||
FULL_NAME = github.com/go-ini/%(NAME)s
|
||||
```
|
||||
|
||||
```go
|
||||
cfg.Section("author").Key("GITHUB").String() // https://github.com/Unknwon
|
||||
cfg.Section("package").Key("FULL_NAME").String() // github.com/go-ini/ini
|
||||
```
|
||||
|
||||
### 读取父子分区
|
||||
|
||||
您可以在分区名称中使用 `.` 来表示两个或多个分区之间的父子关系。如果某个键在子分区中不存在,则会去它的父分区中再次寻找,直到没有父分区为止。
|
||||
|
||||
```ini
|
||||
NAME = ini
|
||||
VERSION = v1
|
||||
IMPORT_PATH = gopkg.in/%(NAME)s.%(VERSION)s
|
||||
|
||||
[package]
|
||||
CLONE_URL = https://%(IMPORT_PATH)s
|
||||
|
||||
[package.sub]
|
||||
```
|
||||
|
||||
```go
|
||||
cfg.Section("package.sub").Key("CLONE_URL").String() // https://gopkg.in/ini.v1
|
||||
```
|
||||
|
||||
#### 获取上级父分区下的所有键名
|
||||
|
||||
```go
|
||||
cfg.Section("package.sub").ParentKeys() // ["CLONE_URL"]
|
||||
```
|
||||
|
||||
### 无法解析的分区
|
||||
|
||||
如果遇到一些比较特殊的分区,它们不包含常见的键值对,而是没有固定格式的纯文本,则可以使用 `LoadOptions.UnparsableSections` 进行处理:
|
||||
|
||||
```go
|
||||
cfg, err := LoadSources(ini.LoadOptions{UnparseableSections: []string{"COMMENTS"}}, `[COMMENTS]
|
||||
<1><L.Slide#2> This slide has the fuel listed in the wrong units <e.1>`))
|
||||
|
||||
body := cfg.Section("COMMENTS").Body()
|
||||
|
||||
/* --- start ---
|
||||
<1><L.Slide#2> This slide has the fuel listed in the wrong units <e.1>
|
||||
------ end --- */
|
||||
```
|
||||
|
||||
### 读取自增键名
|
||||
|
||||
如果数据源中的键名为 `-`,则认为该键使用了自增键名的特殊语法。计数器从 1 开始,并且分区之间是相互独立的。
|
||||
|
||||
```ini
|
||||
[features]
|
||||
-: Support read/write comments of keys and sections
|
||||
-: Support auto-increment of key names
|
||||
-: Support load multiple files to overwrite key values
|
||||
```
|
||||
|
||||
```go
|
||||
cfg.Section("features").KeyStrings() // []{"#1", "#2", "#3"}
|
||||
```
|
||||
|
||||
### 映射到结构
|
||||
|
||||
想要使用更加面向对象的方式玩转 INI 吗?好主意。
|
||||
|
||||
```ini
|
||||
Name = Unknwon
|
||||
age = 21
|
||||
Male = true
|
||||
Born = 1993-01-01T20:17:05Z
|
||||
|
||||
[Note]
|
||||
Content = Hi is a good man!
|
||||
Cities = HangZhou, Boston
|
||||
```
|
||||
|
||||
```go
|
||||
type Note struct {
|
||||
Content string
|
||||
Cities []string
|
||||
}
|
||||
|
||||
type Person struct {
|
||||
Name string
|
||||
Age int `ini:"age"`
|
||||
Male bool
|
||||
Born time.Time
|
||||
Note
|
||||
Created time.Time `ini:"-"`
|
||||
}
|
||||
|
||||
func main() {
|
||||
cfg, err := ini.Load("path/to/ini")
|
||||
// ...
|
||||
p := new(Person)
|
||||
err = cfg.MapTo(p)
|
||||
// ...
|
||||
|
||||
// 一切竟可以如此的简单。
|
||||
err = ini.MapTo(p, "path/to/ini")
|
||||
// ...
|
||||
|
||||
// 嗯哼?只需要映射一个分区吗?
|
||||
n := new(Note)
|
||||
err = cfg.Section("Note").MapTo(n)
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
结构的字段怎么设置默认值呢?很简单,只要在映射之前对指定字段进行赋值就可以了。如果键未找到或者类型错误,该值不会发生改变。
|
||||
|
||||
```go
|
||||
// ...
|
||||
p := &Person{
|
||||
Name: "Joe",
|
||||
}
|
||||
// ...
|
||||
```
|
||||
|
||||
这样玩 INI 真的好酷啊!然而,如果不能还给我原来的配置文件,有什么卵用?
|
||||
|
||||
### 从结构反射
|
||||
|
||||
可是,我有说不能吗?
|
||||
|
||||
```go
|
||||
type Embeded struct {
|
||||
Dates []time.Time `delim:"|" comment:"Time data"`
|
||||
Places []string `ini:"places,omitempty"`
|
||||
None []int `ini:",omitempty"`
|
||||
}
|
||||
|
||||
type Author struct {
|
||||
Name string `ini:"NAME"`
|
||||
Male bool
|
||||
Age int `comment:"Author's age"`
|
||||
GPA float64
|
||||
NeverMind string `ini:"-"`
|
||||
*Embeded `comment:"Embeded section"`
|
||||
}
|
||||
|
||||
func main() {
|
||||
a := &Author{"Unknwon", true, 21, 2.8, "",
|
||||
&Embeded{
|
||||
[]time.Time{time.Now(), time.Now()},
|
||||
[]string{"HangZhou", "Boston"},
|
||||
[]int{},
|
||||
}}
|
||||
cfg := ini.Empty()
|
||||
err = ini.ReflectFrom(cfg, a)
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
瞧瞧,奇迹发生了。
|
||||
|
||||
```ini
|
||||
NAME = Unknwon
|
||||
Male = true
|
||||
; Author's age
|
||||
Age = 21
|
||||
GPA = 2.8
|
||||
|
||||
; Embeded section
|
||||
[Embeded]
|
||||
; Time data
|
||||
Dates = 2015-08-07T22:14:22+08:00|2015-08-07T22:14:22+08:00
|
||||
places = HangZhou,Boston
|
||||
```
|
||||
|
||||
#### 名称映射器(Name Mapper)
|
||||
|
||||
为了节省您的时间并简化代码,本库支持类型为 [`NameMapper`](https://gowalker.org/gopkg.in/ini.v1#NameMapper) 的名称映射器,该映射器负责结构字段名与分区名和键名之间的映射。
|
||||
|
||||
目前有 2 款内置的映射器:
|
||||
|
||||
- `AllCapsUnderscore`:该映射器将字段名转换至格式 `ALL_CAPS_UNDERSCORE` 后再去匹配分区名和键名。
|
||||
- `TitleUnderscore`:该映射器将字段名转换至格式 `title_underscore` 后再去匹配分区名和键名。
|
||||
|
||||
使用方法:
|
||||
|
||||
```go
|
||||
type Info struct{
|
||||
PackageName string
|
||||
}
|
||||
|
||||
func main() {
|
||||
err = ini.MapToWithMapper(&Info{}, ini.TitleUnderscore, []byte("package_name=ini"))
|
||||
// ...
|
||||
|
||||
cfg, err := ini.Load([]byte("PACKAGE_NAME=ini"))
|
||||
// ...
|
||||
info := new(Info)
|
||||
cfg.NameMapper = ini.AllCapsUnderscore
|
||||
err = cfg.MapTo(info)
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
使用函数 `ini.ReflectFromWithMapper` 时也可应用相同的规则。
|
||||
|
||||
#### 值映射器(Value Mapper)
|
||||
|
||||
值映射器允许使用一个自定义函数自动展开值的具体内容,例如:运行时获取环境变量:
|
||||
|
||||
```go
|
||||
type Env struct {
|
||||
Foo string `ini:"foo"`
|
||||
}
|
||||
|
||||
func main() {
|
||||
cfg, err := ini.Load([]byte("[env]\nfoo = ${MY_VAR}\n")
|
||||
cfg.ValueMapper = os.ExpandEnv
|
||||
// ...
|
||||
env := &Env{}
|
||||
err = cfg.Section("env").MapTo(env)
|
||||
}
|
||||
```
|
||||
|
||||
本例中,`env.Foo` 将会是运行时所获取到环境变量 `MY_VAR` 的值。
|
||||
|
||||
#### 映射/反射的其它说明
|
||||
|
||||
任何嵌入的结构都会被默认认作一个不同的分区,并且不会自动产生所谓的父子分区关联:
|
||||
|
||||
```go
|
||||
type Child struct {
|
||||
Age string
|
||||
}
|
||||
|
||||
type Parent struct {
|
||||
Name string
|
||||
Child
|
||||
}
|
||||
|
||||
type Config struct {
|
||||
City string
|
||||
Parent
|
||||
}
|
||||
```
|
||||
|
||||
示例配置文件:
|
||||
|
||||
```ini
|
||||
City = Boston
|
||||
|
||||
[Parent]
|
||||
Name = Unknwon
|
||||
|
||||
[Child]
|
||||
Age = 21
|
||||
```
|
||||
|
||||
很好,但是,我就是要嵌入结构也在同一个分区。好吧,你爹是李刚!
|
||||
|
||||
```go
|
||||
type Child struct {
|
||||
Age string
|
||||
}
|
||||
|
||||
type Parent struct {
|
||||
Name string
|
||||
Child `ini:"Parent"`
|
||||
}
|
||||
|
||||
type Config struct {
|
||||
City string
|
||||
Parent
|
||||
}
|
||||
```
|
||||
|
||||
示例配置文件:
|
||||
|
||||
```ini
|
||||
City = Boston
|
||||
|
||||
[Parent]
|
||||
Name = Unknwon
|
||||
Age = 21
|
||||
```
|
||||
|
||||
## 获取帮助
|
||||
|
||||
- [API 文档](https://gowalker.org/gopkg.in/ini.v1)
|
||||
- [创建工单](https://github.com/go-ini/ini/issues/new)
|
||||
|
||||
## 常见问题
|
||||
|
||||
### 字段 `BlockMode` 是什么?
|
||||
|
||||
默认情况下,本库会在您进行读写操作时采用锁机制来确保数据时间。但在某些情况下,您非常确定只进行读操作。此时,您可以通过设置 `cfg.BlockMode = false` 来将读操作提升大约 **50-70%** 的性能。
|
||||
|
||||
### 为什么要写另一个 INI 解析库?
|
||||
|
||||
许多人都在使用我的 [goconfig](https://github.com/Unknwon/goconfig) 来完成对 INI 文件的操作,但我希望使用更加 Go 风格的代码。并且当您设置 `cfg.BlockMode = false` 时,会有大约 **10-30%** 的性能提升。
|
||||
|
||||
为了做出这些改变,我必须对 API 进行破坏,所以新开一个仓库是最安全的做法。除此之外,本库直接使用 `gopkg.in` 来进行版本化发布。(其实真相是导入路径更短了)
|
42
vendor/gopkg.in/ldap.v2/Makefile
generated
vendored
42
vendor/gopkg.in/ldap.v2/Makefile
generated
vendored
|
@ -1,42 +0,0 @@
|
|||
.PHONY: default install build test quicktest fmt vet lint
|
||||
|
||||
default: fmt vet lint build quicktest
|
||||
|
||||
install:
|
||||
go get -t -v ./...
|
||||
|
||||
build:
|
||||
go build -v ./...
|
||||
|
||||
test:
|
||||
go test -v -cover ./...
|
||||
|
||||
quicktest:
|
||||
go test ./...
|
||||
|
||||
# Capture output and force failure when there is non-empty output
|
||||
fmt:
|
||||
@echo gofmt -l .
|
||||
@OUTPUT=`gofmt -l . 2>&1`; \
|
||||
if [ "$$OUTPUT" ]; then \
|
||||
echo "gofmt must be run on the following files:"; \
|
||||
echo "$$OUTPUT"; \
|
||||
exit 1; \
|
||||
fi
|
||||
|
||||
# Only run on go1.5+
|
||||
vet:
|
||||
go tool vet -atomic -bool -copylocks -nilfunc -printf -shadow -rangeloops -unreachable -unsafeptr -unusedresult .
|
||||
|
||||
# https://github.com/golang/lint
|
||||
# go get github.com/golang/lint/golint
|
||||
# Capture output and force failure when there is non-empty output
|
||||
# Only run on go1.5+
|
||||
lint:
|
||||
@echo golint ./...
|
||||
@OUTPUT=`golint ./... 2>&1`; \
|
||||
if [ "$$OUTPUT" ]; then \
|
||||
echo "golint errors:"; \
|
||||
echo "$$OUTPUT"; \
|
||||
exit 1; \
|
||||
fi
|
53
vendor/gopkg.in/ldap.v2/README.md
generated
vendored
53
vendor/gopkg.in/ldap.v2/README.md
generated
vendored
|
@ -1,53 +0,0 @@
|
|||
[](https://godoc.org/gopkg.in/ldap.v2)
|
||||
[](https://travis-ci.org/go-ldap/ldap)
|
||||
|
||||
# Basic LDAP v3 functionality for the GO programming language.
|
||||
|
||||
## Install
|
||||
|
||||
For the latest version use:
|
||||
|
||||
go get gopkg.in/ldap.v2
|
||||
|
||||
Import the latest version with:
|
||||
|
||||
import "gopkg.in/ldap.v2"
|
||||
|
||||
## Required Libraries:
|
||||
|
||||
- gopkg.in/asn1-ber.v1
|
||||
|
||||
## Features:
|
||||
|
||||
- Connecting to LDAP server (non-TLS, TLS, STARTTLS)
|
||||
- Binding to LDAP server
|
||||
- Searching for entries
|
||||
- Filter Compile / Decompile
|
||||
- Paging Search Results
|
||||
- Modify Requests / Responses
|
||||
- Add Requests / Responses
|
||||
- Delete Requests / Responses
|
||||
|
||||
## Examples:
|
||||
|
||||
- search
|
||||
- modify
|
||||
|
||||
## Contributing:
|
||||
|
||||
Bug reports and pull requests are welcome!
|
||||
|
||||
Before submitting a pull request, please make sure tests and verification scripts pass:
|
||||
```
|
||||
make all
|
||||
```
|
||||
|
||||
To set up a pre-push hook to run the tests and verify scripts before pushing:
|
||||
```
|
||||
ln -s ../../.githooks/pre-push .git/hooks/pre-push
|
||||
```
|
||||
|
||||
---
|
||||
The Go gopher was designed by Renee French. (http://reneefrench.blogspot.com/)
|
||||
The design is licensed under the Creative Commons 3.0 Attributions license.
|
||||
Read this article for more details: http://blog.golang.org/gopher
|
93
vendor/gopkg.in/macaron.v1/README.md
generated
vendored
93
vendor/gopkg.in/macaron.v1/README.md
generated
vendored
|
@ -1,93 +0,0 @@
|
|||
Macaron [](https://travis-ci.org/go-macaron/macaron)
|
||||
=======================
|
||||
|
||||

|
||||
|
||||
Package macaron is a high productive and modular web framework in Go.
|
||||
|
||||
## Getting Started
|
||||
|
||||
The minimum requirement of Go is **1.3**.
|
||||
|
||||
To install Macaron:
|
||||
|
||||
go get gopkg.in/macaron.v1
|
||||
|
||||
The very basic usage of Macaron:
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import "gopkg.in/macaron.v1"
|
||||
|
||||
func main() {
|
||||
m := macaron.Classic()
|
||||
m.Get("/", func() string {
|
||||
return "Hello world!"
|
||||
})
|
||||
m.Run()
|
||||
}
|
||||
```
|
||||
|
||||
## Features
|
||||
|
||||
- Powerful routing with suburl.
|
||||
- Flexible routes combinations.
|
||||
- Unlimited nested group routers.
|
||||
- Directly integrate with existing services.
|
||||
- Dynamically change template files at runtime.
|
||||
- Allow to use in-memory template and static files.
|
||||
- Easy to plugin/unplugin features with modular design.
|
||||
- Handy dependency injection powered by [inject](https://github.com/codegangsta/inject).
|
||||
- Better router layer and less reflection make faster speed.
|
||||
|
||||
## Middlewares
|
||||
|
||||
Middlewares allow you easily plugin/unplugin features for your Macaron applications.
|
||||
|
||||
There are already many [middlewares](https://github.com/go-macaron) to simplify your work:
|
||||
|
||||
- render - Go template engine
|
||||
- static - Serves static files
|
||||
- [gzip](https://github.com/go-macaron/gzip) - Gzip compression to all responses
|
||||
- [binding](https://github.com/go-macaron/binding) - Request data binding and validation
|
||||
- [i18n](https://github.com/go-macaron/i18n) - Internationalization and Localization
|
||||
- [cache](https://github.com/go-macaron/cache) - Cache manager
|
||||
- [session](https://github.com/go-macaron/session) - Session manager
|
||||
- [csrf](https://github.com/go-macaron/csrf) - Generates and validates csrf tokens
|
||||
- [captcha](https://github.com/go-macaron/captcha) - Captcha service
|
||||
- [pongo2](https://github.com/go-macaron/pongo2) - Pongo2 template engine support
|
||||
- [sockets](https://github.com/go-macaron/sockets) - WebSockets channels binding
|
||||
- [bindata](https://github.com/go-macaron/bindata) - Embed binary data as static and template files
|
||||
- [toolbox](https://github.com/go-macaron/toolbox) - Health check, pprof, profile and statistic services
|
||||
- [oauth2](https://github.com/go-macaron/oauth2) - OAuth 2.0 backend
|
||||
- [authz](https://github.com/go-macaron/authz) - ACL/RBAC/ABAC authorization based on Casbin
|
||||
- [switcher](https://github.com/go-macaron/switcher) - Multiple-site support
|
||||
- [method](https://github.com/go-macaron/method) - HTTP method override
|
||||
- [permissions2](https://github.com/xyproto/permissions2) - Cookies, users and permissions
|
||||
- [renders](https://github.com/go-macaron/renders) - Beego-like render engine(Macaron has built-in template engine, this is another option)
|
||||
- [piwik](https://github.com/veecue/piwik-middleware) - Server-side piwik analytics
|
||||
|
||||
## Use Cases
|
||||
|
||||
- [Gogs](https://gogs.io): A painless self-hosted Git Service
|
||||
- [Grafana](http://grafana.org/): The open platform for beautiful analytics and monitoring
|
||||
- [Peach](https://peachdocs.org): A modern web documentation server
|
||||
- [Go Walker](https://gowalker.org): Go online API documentation
|
||||
- [Switch](https://gopm.io): Gopm registry
|
||||
- [Critical Stack Intel](https://intel.criticalstack.com/): A 100% free intel marketplace from Critical Stack, Inc.
|
||||
|
||||
## Getting Help
|
||||
|
||||
- [API Reference](https://gowalker.org/gopkg.in/macaron.v1)
|
||||
- [Documentation](https://go-macaron.com)
|
||||
- [FAQs](https://go-macaron.com/docs/faqs)
|
||||
|
||||
## Credits
|
||||
|
||||
- Basic design of [Martini](https://github.com/go-martini/martini).
|
||||
- Logo is modified by [@insionng](https://github.com/insionng) based on [Tribal Dragon](http://xtremeyamazaki.deviantart.com/art/Tribal-Dragon-27005087).
|
||||
|
||||
## License
|
||||
|
||||
This project is under the Apache License, Version 2.0. See the [LICENSE](LICENSE) file for the full license text.
|
1
vendor/gopkg.in/macaron.v1/fixtures/symlink
generated
vendored
Symbolic link
1
vendor/gopkg.in/macaron.v1/fixtures/symlink
generated
vendored
Symbolic link
|
@ -0,0 +1 @@
|
|||
basic
|
BIN
vendor/gopkg.in/macaron.v1/macaronlogo.png
generated
vendored
BIN
vendor/gopkg.in/macaron.v1/macaronlogo.png
generated
vendored
Binary file not shown.
Before Width: | Height: | Size: 87 KiB |
3
vendor/gopkg.in/redis.v2/Makefile
generated
vendored
3
vendor/gopkg.in/redis.v2/Makefile
generated
vendored
|
@ -1,3 +0,0 @@
|
|||
all:
|
||||
go test gopkg.in/redis.v2 -cpu=1,2,4
|
||||
go test gopkg.in/redis.v2 -short -race
|
46
vendor/gopkg.in/redis.v2/README.md
generated
vendored
46
vendor/gopkg.in/redis.v2/README.md
generated
vendored
|
@ -1,46 +0,0 @@
|
|||
Redis client for Golang [](https://travis-ci.org/go-redis/redis)
|
||||
=======================
|
||||
|
||||
Supports:
|
||||
|
||||
- Redis 2.8 commands except QUIT, MONITOR, SLOWLOG and SYNC.
|
||||
- Pub/sub.
|
||||
- Transactions.
|
||||
- Pipelining.
|
||||
- Connection pool.
|
||||
- TLS connections.
|
||||
- Thread safety.
|
||||
- Timeouts.
|
||||
- Redis Sentinel.
|
||||
|
||||
API docs: http://godoc.org/gopkg.in/redis.v2.
|
||||
Examples: http://godoc.org/gopkg.in/redis.v2#pkg-examples.
|
||||
|
||||
Installation
|
||||
------------
|
||||
|
||||
Install:
|
||||
|
||||
go get gopkg.in/redis.v2
|
||||
|
||||
Look and feel
|
||||
-------------
|
||||
|
||||
Some corner cases:
|
||||
|
||||
SORT list LIMIT 0 2 ASC
|
||||
vals, err := client.Sort("list", redis.Sort{Offset: 0, Count: 2, Order: "ASC"}).Result()
|
||||
|
||||
ZRANGEBYSCORE zset -inf +inf WITHSCORES LIMIT 0 2
|
||||
vals, err := client.ZRangeByScoreWithScores("zset", redis.ZRangeByScore{
|
||||
Min: "-inf",
|
||||
Max: "+inf",
|
||||
Offset: 0,
|
||||
Count: 2,
|
||||
}).Result()
|
||||
|
||||
ZINTERSTORE out 2 zset1 zset2 WEIGHTS 2 3 AGGREGATE SUM
|
||||
vals, err := client.ZInterStore("out", redis.ZStore{Weights: []int64{2, 3}}, "zset1", "zset2").Result()
|
||||
|
||||
EVAL "return {KEYS[1],ARGV[1]}" 1 "key" "hello"
|
||||
vals, err := client.Eval("return {KEYS[1],ARGV[1]}", []string{"key"}, []string{"hello"}).Result()
|
323
vendor/gopkg.in/testfixtures.v2/README.md
generated
vendored
323
vendor/gopkg.in/testfixtures.v2/README.md
generated
vendored
|
@ -1,323 +0,0 @@
|
|||
# Go Test Fixtures
|
||||
|
||||
[](https://github.com/go-testfixtures/testfixtures/blob/master/LICENSE)
|
||||
[](https://gitter.im/go-testfixtures/testfixtures?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
||||
[](https://godoc.org/gopkg.in/testfixtures.v1)
|
||||
[](https://travis-ci.org/go-testfixtures/testfixtures)
|
||||
[](https://goreportcard.com/report/github.com/go-testfixtures/testfixtures)
|
||||
|
||||
> ***Warning***: this package will wipe the database data before loading the
|
||||
fixtures! It is supposed to be used on a test database. Please, double check
|
||||
if you are running it against the correct database.
|
||||
|
||||
Writing tests is hard, even more when you have to deal with an SQL database.
|
||||
This package aims to make writing functional tests for web apps written in
|
||||
Go easier.
|
||||
|
||||
Basically this package mimics the ["Rails' way"][railstests] of writing tests
|
||||
for database applications, where sample data is kept in fixtures files. Before
|
||||
the execution of every test, the test database is cleaned and the fixture data
|
||||
is loaded into the database.
|
||||
|
||||
The idea is running tests against a real database, instead of relying in mocks,
|
||||
which is boring to setup and may lead to production bugs not to being catch in
|
||||
the tests.
|
||||
|
||||
## Installation
|
||||
|
||||
First, get it:
|
||||
|
||||
```bash
|
||||
go get -u gopkg.in/testfixtures.v2
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
Create a folder for the fixture files. Each file should contain data for a
|
||||
single table and have the name `<table-name>.yml`:
|
||||
|
||||
```yml
|
||||
myapp
|
||||
- myapp.go
|
||||
- myapp_test.go
|
||||
- ...
|
||||
- fixtures:
|
||||
- posts.yml
|
||||
- comments.yml
|
||||
- tags.yml
|
||||
- posts_tags.yml
|
||||
- ...
|
||||
```
|
||||
|
||||
The file would look like this (it can have as many record you want):
|
||||
|
||||
```yml
|
||||
# comments.yml
|
||||
-
|
||||
id: 1
|
||||
post_id: 1
|
||||
content: This post is awesome!
|
||||
author_name: John Doe
|
||||
author_email: john@doe.com
|
||||
created_at: 2016-01-01 12:30:12
|
||||
updated_at: 2016-01-01 12:30:12
|
||||
|
||||
-
|
||||
id: 2
|
||||
post_id: 2
|
||||
content: Are you kidding me?
|
||||
author_name: John Doe
|
||||
author_email: john@doe.com
|
||||
created_at: 2016-01-01 12:30:12
|
||||
updated_at: 2016-01-01 12:30:12
|
||||
|
||||
# ...
|
||||
```
|
||||
|
||||
Your tests would look like this:
|
||||
|
||||
```go
|
||||
package myapp
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"log"
|
||||
|
||||
_ "github.com/lib/pq"
|
||||
"gopkg.in/testfixtures.v2"
|
||||
)
|
||||
|
||||
var (
|
||||
db *sql.DB
|
||||
fixtures *testfixtures.Context
|
||||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
var err error
|
||||
|
||||
// Open connection with the test database.
|
||||
// Do NOT import fixtures in a production database!
|
||||
// Existing data would be deleted
|
||||
db, err = sql.Open("postgres", "dbname=myapp_test")
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
// creating the context that hold the fixtures
|
||||
// see about all compatible databases in this page below
|
||||
c, err = testfixtures.NewFolder(db, &testfixtures.PostgreSQL{}, "testdata/fixtures")
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
os.Exit(m.Run())
|
||||
}
|
||||
|
||||
func prepareTestDatabase() {
|
||||
if err := fixtures.Load(); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestX(t *testing.T) {
|
||||
prepareTestDatabase()
|
||||
// your test here ...
|
||||
}
|
||||
|
||||
func TestY(t *testing.T) {
|
||||
prepareTestDatabase()
|
||||
// your test here ...
|
||||
}
|
||||
|
||||
func TestZ(t *testing.T) {
|
||||
prepareTestDatabase()
|
||||
// your test here ...
|
||||
}
|
||||
```
|
||||
|
||||
Alternatively, you can use the `NewFiles` function, to specify which
|
||||
files you want to load into the database:
|
||||
|
||||
```go
|
||||
fixtures, err := testfixtures.NewFiles(db, &testfixtures.PostgreSQL{},
|
||||
"fixtures/orders.yml",
|
||||
"fixtures/customers.yml",
|
||||
// add as many files you want
|
||||
)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
```
|
||||
|
||||
## Security check
|
||||
|
||||
In order to prevent you from accidentally wiping the wrong database, this
|
||||
package will refuse to load fixtures if the database name (or database
|
||||
filename for SQLite) doesn't contains "test". If you want to disable this
|
||||
check, use:
|
||||
|
||||
```go
|
||||
testfixtures.SkipDatabaseNameCheck(true)
|
||||
```
|
||||
|
||||
## Sequences
|
||||
|
||||
For PostgreSQL or Oracle, this package also resets all sequences to a high
|
||||
number to prevent duplicated primary keys while running the tests.
|
||||
The default is 10000, but you can change that with:
|
||||
|
||||
```go
|
||||
testfixtures.ResetSequencesTo(10000)
|
||||
```
|
||||
|
||||
## Compatible databases
|
||||
|
||||
### PostgreSQL
|
||||
|
||||
This package has two approaches to disable foreign keys while importing fixtures
|
||||
in PostgreSQL databases:
|
||||
|
||||
#### With `DISABLE TRIGGER`
|
||||
|
||||
This is the default approach. For that use:
|
||||
|
||||
```go
|
||||
&testfixtures.PostgreSQL{}
|
||||
```
|
||||
|
||||
With the above snippet this package will use `DISABLE TRIGGER` to temporarily
|
||||
disabling foreign key constraints while loading fixtures. This work with any
|
||||
version of PostgreSQL, but it is **required** to be connected in the database
|
||||
as a SUPERUSER. You can make a PostgreSQL user a SUPERUSER with:
|
||||
|
||||
```sql
|
||||
ALTER USER your_user SUPERUSER;
|
||||
```
|
||||
|
||||
#### With `ALTER CONSTRAINT`
|
||||
|
||||
This approach don't require to be connected as a SUPERUSER, but only work with
|
||||
PostgreSQL versions >= 9.4. Try this if you are getting foreign key violation
|
||||
errors with the previous approach. It is as simple as using:
|
||||
|
||||
```go
|
||||
&testfixtures.PostgreSQL{UseAlterConstraint: true}
|
||||
```
|
||||
|
||||
### MySQL
|
||||
|
||||
Just make sure the connection string have
|
||||
[the multistatement parameter](https://github.com/go-sql-driver/mysql#multistatements)
|
||||
set to true, and use:
|
||||
|
||||
```go
|
||||
&testfixtures.MySQL{}
|
||||
```
|
||||
|
||||
### SQLite
|
||||
|
||||
SQLite is also supported. It is recommended to create foreign keys as
|
||||
`DEFERRABLE` (the default) to prevent problems. See more
|
||||
[on the SQLite documentation](https://www.sqlite.org/foreignkeys.html#fk_deferred).
|
||||
(Foreign key constraints are no-op by default on SQLite, but enabling it is
|
||||
recommended).
|
||||
|
||||
```go
|
||||
&testfixtures.SQLite{}
|
||||
```
|
||||
|
||||
### Microsoft SQL Server
|
||||
|
||||
SQL Server support requires SQL Server >= 2008. Inserting on `IDENTITY` columns
|
||||
are handled as well. Just make sure you are logged in with a user with
|
||||
`ALTER TABLE` permission.
|
||||
|
||||
```go
|
||||
&testfixtures.SQLServer{}
|
||||
```
|
||||
|
||||
### Oracle
|
||||
|
||||
Oracle is supported as well. Use:
|
||||
|
||||
```go
|
||||
&testfixtures.Oracle{}
|
||||
```
|
||||
|
||||
## Contributing
|
||||
|
||||
Tests were written to ensure everything work as expected. You can run the tests
|
||||
with:
|
||||
|
||||
```bash
|
||||
# running tests for PostgreSQL
|
||||
go test -tags postgresql
|
||||
|
||||
# running test for MySQL
|
||||
go test -tags mysql
|
||||
|
||||
# running tests for SQLite
|
||||
go test -tags sqlite
|
||||
|
||||
# running tests for SQL Server
|
||||
go test -tags sqlserver
|
||||
|
||||
# running tests for Oracle
|
||||
go test -tags oracle
|
||||
|
||||
# running test for multiple databases at once
|
||||
go test -tags 'sqlite postgresql mysql'
|
||||
|
||||
# running tests + benchmark
|
||||
go test -v -bench=. -tags postgresql
|
||||
```
|
||||
|
||||
Travis runs tests for PostgreSQL, MySQL and SQLite.
|
||||
|
||||
To set the connection string of tests for each database, edit the `.env`
|
||||
file, but do not include the changes a in pull request.
|
||||
|
||||
## Changes in v2
|
||||
|
||||
A context was created to allow cache of some SQL statements. See in the
|
||||
documentation above how to use it.
|
||||
|
||||
The helpers were renamed to have a smaller name:
|
||||
|
||||
```go
|
||||
PostgreSQLHelper{} -> PostgreSQL{}
|
||||
MySQLHelper{} -> MySQL{}
|
||||
SQLiteHelper{} -> SQLite{}
|
||||
SQLServerHelper{} -> SQLServer{}
|
||||
OracleHelper{} -> Oracle{}
|
||||
```
|
||||
|
||||
The old functions and helpers are still available for backward compatibility.
|
||||
See the file [deprecated.go](https://github.com/go-testfixtures/testfixtures/blob/master/LICENSE)
|
||||
|
||||
## Alternatives
|
||||
|
||||
If you don't think using fixtures is a good idea, you can try one of these
|
||||
packages instead:
|
||||
|
||||
- [factory-go][factorygo]: Factory for Go. Inspired by Python's Factory Boy
|
||||
and Ruby's Factory Girl
|
||||
- [go-txdb (Single transaction SQL driver for Go)][gotxdb]: Use a single
|
||||
database transaction for each functional test, so you can rollback to
|
||||
previous state between tests to have the same database state in all tests
|
||||
- [go-sqlmock][gosqlmock]: A mock for the sql.DB interface. This allow you to unit
|
||||
test database code without having to connect to a real database
|
||||
|
||||
There's also these other implementations of test fixtures for Go:
|
||||
|
||||
- [go-fixtures][gofixtures]: Django style fixtures for Go
|
||||
- [mongofixtures][mongofixtures]: Fixtures for MongoDB
|
||||
- [fixturer][fixturer]: Another fixture loader supporting MySQL
|
||||
|
||||
[railstests]: http://guides.rubyonrails.org/testing.html#the-test-database
|
||||
[gotxdb]: https://github.com/DATA-DOG/go-txdb
|
||||
[gosqlmock]: https://github.com/DATA-DOG/go-sqlmock
|
||||
[gofixtures]: https://github.com/AreaHQ/go-fixtures
|
||||
[mongofixtures]: https://github.com/OwlyCode/mongofixtures
|
||||
[fixturer]: https://github.com/44hapa/fixturer
|
||||
[factorygo]: https://github.com/bluele/factory-go
|
131
vendor/gopkg.in/yaml.v2/README.md
generated
vendored
131
vendor/gopkg.in/yaml.v2/README.md
generated
vendored
|
@ -1,131 +0,0 @@
|
|||
# YAML support for the Go language
|
||||
|
||||
Introduction
|
||||
------------
|
||||
|
||||
The yaml package enables Go programs to comfortably encode and decode YAML
|
||||
values. It was developed within [Canonical](https://www.canonical.com) as
|
||||
part of the [juju](https://juju.ubuntu.com) project, and is based on a
|
||||
pure Go port of the well-known [libyaml](http://pyyaml.org/wiki/LibYAML)
|
||||
C library to parse and generate YAML data quickly and reliably.
|
||||
|
||||
Compatibility
|
||||
-------------
|
||||
|
||||
The yaml package supports most of YAML 1.1 and 1.2, including support for
|
||||
anchors, tags, map merging, etc. Multi-document unmarshalling is not yet
|
||||
implemented, and base-60 floats from YAML 1.1 are purposefully not
|
||||
supported since they're a poor design and are gone in YAML 1.2.
|
||||
|
||||
Installation and usage
|
||||
----------------------
|
||||
|
||||
The import path for the package is *gopkg.in/yaml.v2*.
|
||||
|
||||
To install it, run:
|
||||
|
||||
go get gopkg.in/yaml.v2
|
||||
|
||||
API documentation
|
||||
-----------------
|
||||
|
||||
If opened in a browser, the import path itself leads to the API documentation:
|
||||
|
||||
* [https://gopkg.in/yaml.v2](https://gopkg.in/yaml.v2)
|
||||
|
||||
API stability
|
||||
-------------
|
||||
|
||||
The package API for yaml v2 will remain stable as described in [gopkg.in](https://gopkg.in).
|
||||
|
||||
|
||||
License
|
||||
-------
|
||||
|
||||
The yaml package is licensed under the Apache License 2.0. Please see the LICENSE file for details.
|
||||
|
||||
|
||||
Example
|
||||
-------
|
||||
|
||||
```Go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
|
||||
"gopkg.in/yaml.v2"
|
||||
)
|
||||
|
||||
var data = `
|
||||
a: Easy!
|
||||
b:
|
||||
c: 2
|
||||
d: [3, 4]
|
||||
`
|
||||
|
||||
type T struct {
|
||||
A string
|
||||
B struct {
|
||||
RenamedC int `yaml:"c"`
|
||||
D []int `yaml:",flow"`
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
t := T{}
|
||||
|
||||
err := yaml.Unmarshal([]byte(data), &t)
|
||||
if err != nil {
|
||||
log.Fatalf("error: %v", err)
|
||||
}
|
||||
fmt.Printf("--- t:\n%v\n\n", t)
|
||||
|
||||
d, err := yaml.Marshal(&t)
|
||||
if err != nil {
|
||||
log.Fatalf("error: %v", err)
|
||||
}
|
||||
fmt.Printf("--- t dump:\n%s\n\n", string(d))
|
||||
|
||||
m := make(map[interface{}]interface{})
|
||||
|
||||
err = yaml.Unmarshal([]byte(data), &m)
|
||||
if err != nil {
|
||||
log.Fatalf("error: %v", err)
|
||||
}
|
||||
fmt.Printf("--- m:\n%v\n\n", m)
|
||||
|
||||
d, err = yaml.Marshal(&m)
|
||||
if err != nil {
|
||||
log.Fatalf("error: %v", err)
|
||||
}
|
||||
fmt.Printf("--- m dump:\n%s\n\n", string(d))
|
||||
}
|
||||
```
|
||||
|
||||
This example will generate the following output:
|
||||
|
||||
```
|
||||
--- t:
|
||||
{Easy! {2 [3 4]}}
|
||||
|
||||
--- t dump:
|
||||
a: Easy!
|
||||
b:
|
||||
c: 2
|
||||
d: [3, 4]
|
||||
|
||||
|
||||
--- m:
|
||||
map[a:Easy! b:map[c:2 d:[3 4]]]
|
||||
|
||||
--- m dump:
|
||||
a: Easy!
|
||||
b:
|
||||
c: 2
|
||||
d:
|
||||
- 3
|
||||
- 4
|
||||
```
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue