url

package
v1.23.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 14, 2024 License: MIT Imports: 0 Imported by: 0

Documentation

Overview

urlパッケージはURLを解析し、クエリのエスケープを実装します。

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func JoinPath added in v1.19.0

func JoinPath(base string, elem ...string) (result string, err error)

JoinPathは、指定されたパス要素が結合された URL 文字列を返します。 ベースの既存パスと生成されたパスは、"./"や"../"要素が除去された状態でクリーンになります。

func PathEscape added in v1.8.0

func PathEscape(s string) string

PathEscapeは、文字列を安全に URL パスセグメント内に配置できるようにエスケープします。 必要に応じて特殊文字(/を含む)を%XXシーケンスで置き換えます。

Example
package main

import (
	"github.com/shogo82148/std/fmt"
	"github.com/shogo82148/std/net/url"
)

func main() {
	path := url.PathEscape("my/cool+blog&about,stuff")
	fmt.Println(path)

}
Output:

my%2Fcool+blog&about%2Cstuff

func PathUnescape added in v1.8.0

func PathUnescape(s string) (string, error)

PathUnescapeは PathEscape の逆の変換を行います。形式が"%AB"の各3バイトエンコードされた部分文字列をhexデコードされたバイト0xABに変換します。もし%の後に2桁の16進数が続かない場合、エラーが返されます。

PathUnescapeは QueryUnescape と同じですが、'+'を' '(スペース)に変換しない点が異なります。

Example
package main

import (
	"github.com/shogo82148/std/fmt"
	"github.com/shogo82148/std/log"
	"github.com/shogo82148/std/net/url"
)

func main() {
	escapedPath := "my%2Fcool+blog&about%2Cstuff"
	path, err := url.PathUnescape(escapedPath)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(path)

}
Output:

my/cool+blog&about,stuff

func QueryEscape

func QueryEscape(s string) string

QueryEscapeは、文字列をエスケープして、安全に URL クエリ内に配置できるようにします。

Example
package main

import (
	"github.com/shogo82148/std/fmt"
	"github.com/shogo82148/std/net/url"
)

func main() {
	query := url.QueryEscape("my/cool+blog&about,stuff")
	fmt.Println(query)

}
Output:

my%2Fcool%2Bblog%26about%2Cstuff

func QueryUnescape

func QueryUnescape(s string) (string, error)

QueryUnescapeは QueryEscape の逆変換を行います "%AB"のような形式の3バイトエンコードされた部分文字列を 16進数でデコードされたバイト0xABに変換します もし%の後に2桁の16進数が続かない場合、エラーが返されます。

Example
package main

import (
	"github.com/shogo82148/std/fmt"
	"github.com/shogo82148/std/log"
	"github.com/shogo82148/std/net/url"
)

func main() {
	escapedQuery := "my%2Fcool%2Bblog%26about%2Cstuff"
	query, err := url.QueryUnescape(escapedQuery)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(query)

}
Output:

my/cool+blog&about,stuff

Types

type Error

type Error struct {
	Op  string
	URL string
	Err error
}

Errorはエラーと、それが発生した操作とURLを報告します。

func (*Error) Error

func (e *Error) Error() string

func (*Error) Temporary added in v1.6.0

func (e *Error) Temporary() bool

func (*Error) Timeout added in v1.6.0

func (e *Error) Timeout() bool

func (*Error) Unwrap added in v1.13.0

func (e *Error) Unwrap() error

type EscapeError

type EscapeError string

func (EscapeError) Error

func (e EscapeError) Error() string

type InvalidHostError added in v1.6.0

type InvalidHostError string

func (InvalidHostError) Error added in v1.6.0

func (e InvalidHostError) Error() string

type URL

type URL struct {
	Scheme      string
	Opaque      string
	User        *Userinfo
	Host        string
	Path        string
	RawPath     string
	OmitHost    bool
	ForceQuery  bool
	RawQuery    string
	Fragment    string
	RawFragment string
}

URLは解析されたURL(厳密にはURIリファレンス)を表します。

全般的な形式は次のようになります:

[スキーム:][//[ユーザー情報@]ホスト][/パス][?クエリ][#フラグメント]

スキームの後にスラッシュで始まらないURLは次のように解釈されます:

スキーム:透明部分[?クエリ][#フラグメント]

Hostフィールドには、URLのホストとポートのサブコンポーネントが含まれます。 ポートが存在する場合、コロンでホストから分離されます。 ホストがIPv6アドレスの場合、角括弧で囲む必要があります: "[fe80::1]:80"。 net.JoinHostPort 関数は、必要に応じてホストに角括弧を追加して、ホストとポートを文字列に結合します。

Pathフィールドは、デコードされた形式で保存されます:/%47%6f%2fは/Go/になります。 結果として、Path内のどのスラッシュが生のURL内のスラッシュであり、どのスラッシュが%2fであるかを区別することはできません。 この区別はほとんど重要ではありませんが、重要な場合は、コードは URL.EscapedPath メソッドを使用する必要があります。 このメソッドは、Pathの元のエンコーディングを保持します。

RawPathフィールドは、デフォルトのパスのエンコードがエスケープされたパスと異なる場合にのみ設定されるオプションのフィールドです。 詳細については、EscapedPathメソッドを参照してください。

URLのStringメソッドは、パスを取得するためにEscapedPathメソッドを使用します。

Example
package main

import (
	"github.com/shogo82148/std/fmt"
	"github.com/shogo82148/std/log"
	"github.com/shogo82148/std/net/url"
)

func main() {
	u, err := url.Parse("http://bing.com/search?q=dotnet")
	if err != nil {
		log.Fatal(err)
	}
	u.Scheme = "https"
	u.Host = "google.com"
	q := u.Query()
	q.Set("q", "golang")
	u.RawQuery = q.Encode()
	fmt.Println(u)
}
Output:

https://google.com/search?q=golang
Example (Roundtrip)
package main

import (
	"github.com/shogo82148/std/fmt"
	"github.com/shogo82148/std/log"
	"github.com/shogo82148/std/net/url"
)

func main() {
	// Parse + Stringは元のエンコーディングを保持します。
	u, err := url.Parse("https://example.com/foo%2fbar")
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(u.Path)
	fmt.Println(u.RawPath)
	fmt.Println(u.String())
}
Output:

/foo/bar
/foo%2fbar
https://example.com/foo%2fbar

func Parse

func Parse(rawURL string) (*URL, error)

Parseは生のURLを URL 構造に解析します。

URLは相対的なもの(ホストなしのパス)または絶対的なもの(スキームで始まる)である可能性があります。 スキームなしでホスト名とパスを解析しようとすることは無効ですが、解析の曖昧さにより、 エラーを返さない場合があります。

func ParseRequestURI

func ParseRequestURI(rawURL string) (*URL, error)

ParseRequestURIは生のURLを URL 構造体に解析します。これは、URLがHTTPリクエストで受け取られたものであることを前提としており、urlは絶対URIまたは絶対パスとしてのみ解釈されます。 文字列urlには#fragmentの接尾辞がないことが前提とされています。 (ウェブブラウザはURLをウェブサーバーに送信する前に#fragmentを取り除きます。)

func (*URL) AppendBinary added in v1.23.0

func (u *URL) AppendBinary(b []byte) ([]byte, error)

func (*URL) EscapedFragment added in v1.15.0

func (u *URL) EscapedFragment() string

EscapedFragmentはu.Fragmentのエスケープ形式を返します。 一般的には、任意のフラグメントには複数のエスケープ形式が存在します。 u.Fragmentが有効なエスケープである場合、EscapedFragmentはu.RawFragmentを返します。 そうでない場合、EscapedFragmentはu.RawFragmentを無視し、独自のエスケープ形式を計算します。 URL.String メソッドは、その結果を構築するためにEscapedFragmentを使用します。 一般的には、コードはu.RawFragmentを直接読む代わりにEscapedFragmentを呼び出すべきです。

Example
package main

import (
	"github.com/shogo82148/std/fmt"
	"github.com/shogo82148/std/log"
	"github.com/shogo82148/std/net/url"
)

func main() {
	u, err := url.Parse("http://example.com/#x/y%2Fz")
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println("Fragment:", u.Fragment)
	fmt.Println("RawFragment:", u.RawFragment)
	fmt.Println("EscapedFragment:", u.EscapedFragment())
}
Output:

Fragment: x/y/z
RawFragment: x/y%2Fz
EscapedFragment: x/y%2Fz

func (*URL) EscapedPath added in v1.5.0

func (u *URL) EscapedPath() string

EscapedPathはu.Pathのエスケープされた形式を返します。 一般的には、任意のパスには複数のエスケープされた形式が存在します。 EscapedPathはu.RawPathがu.Pathの有効なエスケープである場合にはu.RawPathを返します。 そうでない場合、EscapedPathはu.RawPathを無視し、独自のエスケープ形式を計算します。 URL.String メソッドと URL.RequestURI メソッドは、それぞれの結果を構築するためにEscapedPathを使用します。 一般的に、コードはu.RawPathを直接読むのではなく、EscapedPathを呼び出すべきです。

Example
package main

import (
	"github.com/shogo82148/std/fmt"
	"github.com/shogo82148/std/log"
	"github.com/shogo82148/std/net/url"
)

func main() {
	u, err := url.Parse("http://example.com/x/y%2Fz")
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println("Path:", u.Path)
	fmt.Println("RawPath:", u.RawPath)
	fmt.Println("EscapedPath:", u.EscapedPath())
}
Output:

Path: /x/y/z
RawPath: /x/y%2Fz
EscapedPath: /x/y%2Fz

func (*URL) Hostname added in v1.8.0

func (u *URL) Hostname() string

Hostnameは、存在する場合は有効なポート番号を削除してu.Hostを返します。

結果が角かっこで囲まれている場合、それはリテラルIPv6アドレスですので、 結果から角かっこは削除されます。

Example
package main

import (
	"github.com/shogo82148/std/fmt"
	"github.com/shogo82148/std/log"
	"github.com/shogo82148/std/net/url"
)

func main() {
	u, err := url.Parse("https://example.org:8000/path")
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(u.Hostname())
	u, err = url.Parse("https://[2001:0db8:85a3:0000:0000:8a2e:0370:7334]:17000")
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(u.Hostname())
}
Output:

example.org
2001:0db8:85a3:0000:0000:8a2e:0370:7334

func (*URL) IsAbs

func (u *URL) IsAbs() bool

IsAbsは URL が絶対であるかどうかを報告します。 絶対とは、空ではないスキームを持っていることを意味します。

Example
package main

import (
	"github.com/shogo82148/std/fmt"
	"github.com/shogo82148/std/net/url"
)

func main() {
	u := url.URL{Host: "example.com", Path: "foo"}
	fmt.Println(u.IsAbs())
	u.Scheme = "http"
	fmt.Println(u.IsAbs())
}
Output:

false
true

func (*URL) JoinPath added in v1.19.0

func (u *URL) JoinPath(elem ...string) *URL

JoinPath は、指定されたパス要素が既存のパスに結合され、 結果のパスが "./" や "../" の要素を除去された新しい URL を返します。 連続する複数の / 文字のシーケンスは、単一の / に縮小されます。

func (*URL) MarshalBinary added in v1.8.0

func (u *URL) MarshalBinary() (text []byte, err error)
Example
package main

import (
	"github.com/shogo82148/std/fmt"
	"github.com/shogo82148/std/log"
	"github.com/shogo82148/std/net/url"
)

func main() {
	u, _ := url.Parse("https://example.org")
	b, err := u.MarshalBinary()
	if err != nil {
		log.Fatal(err)
	}
	fmt.Printf("%s\n", b)
}
Output:

https://example.org

func (*URL) Parse

func (u *URL) Parse(ref string) (*URL, error)

Parseはレシーバのコンテキストで URL を解析します。提供されたURLは相対的または絶対的である可能性があります。Parseは解析の失敗時にはnil、errを返し、それ以外の場合は URL.ResolveReference と同じ値を返します。

Example
package main

import (
	"github.com/shogo82148/std/fmt"
	"github.com/shogo82148/std/log"
	"github.com/shogo82148/std/net/url"
)

func main() {
	u, err := url.Parse("https://example.org")
	if err != nil {
		log.Fatal(err)
	}
	rel, err := u.Parse("/foo")
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(rel)
	_, err = u.Parse(":foo")
	if _, ok := err.(*url.Error); !ok {
		log.Fatal(err)
	}
}
Output:

https://example.org/foo

func (*URL) Port added in v1.8.0

func (u *URL) Port() string

Portはu.Hostのポート部分を返しますが、先頭のコロンは除かれます。

もしu.Hostに有効な数値のポートが含まれていない場合、Portは空の文字列を返します。

Example
package main

import (
	"github.com/shogo82148/std/fmt"
	"github.com/shogo82148/std/log"
	"github.com/shogo82148/std/net/url"
)

func main() {
	u, err := url.Parse("https://example.org")
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(u.Port())
	u, err = url.Parse("https://example.org:8080")
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(u.Port())
}
Output:


8080

func (*URL) Query

func (u *URL) Query() Values

QueryはRawQueryを解析し、対応する値を返します。 不正な値の組み合わせは静かに破棄されます。 エラーをチェックするには ParseQuery を使用してください。

Example
package main

import (
	"github.com/shogo82148/std/fmt"
	"github.com/shogo82148/std/log"
	"github.com/shogo82148/std/net/url"
)

func main() {
	u, err := url.Parse("https://example.org/?a=1&a=2&b=&=3&&&&")
	if err != nil {
		log.Fatal(err)
	}
	q := u.Query()
	fmt.Println(q["a"])
	fmt.Println(q.Get("b"))
	fmt.Println(q.Get(""))
}
Output:

[1 2]

3

func (*URL) Redacted added in v1.15.0

func (u *URL) Redacted() string

Redactedは URL.String と似ていますが、パスワードを「xxxxx」で置き換えます。 u.User内のパスワードのみが伏せられます。

Example
package main

import (
	"github.com/shogo82148/std/fmt"
	"github.com/shogo82148/std/net/url"
)

func main() {
	u := &url.URL{
		Scheme: "https",
		User:   url.UserPassword("user", "password"),
		Host:   "example.com",
		Path:   "foo/bar",
	}
	fmt.Println(u.Redacted())
	u.User = url.UserPassword("me", "newerPassword")
	fmt.Println(u.Redacted())
}
Output:

https://user:xxxxx@example.com/foo/bar
https://me:xxxxx@example.com/foo/bar

func (*URL) RequestURI

func (u *URL) RequestURI() string

RequestURIは、uのHTTPリクエストで使用される、エンコードされたpath?queryまたはopaque?queryの文字列を返します。

Example
package main

import (
	"github.com/shogo82148/std/fmt"
	"github.com/shogo82148/std/log"
	"github.com/shogo82148/std/net/url"
)

func main() {
	u, err := url.Parse("https://example.org/path?foo=bar")
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(u.RequestURI())
}
Output:

/path?foo=bar

func (*URL) ResolveReference

func (u *URL) ResolveReference(ref *URL) *URL

ResolveReferenceは、RFC 3986 Section 5.2 に従って、絶対ベースURI uからURIリファレンスを絶対URIに解決します。URIリファレンスは相対または絶対のどちらでもかまいません。ResolveReferenceは常に新しい URL インスタンスを返しますが、返されたURLがベースまたはリファレンスと同じであってもです。refが絶対URLの場合、ResolveReferenceはbaseを無視してrefのコピーを返します。

Example
package main

import (
	"github.com/shogo82148/std/fmt"
	"github.com/shogo82148/std/log"
	"github.com/shogo82148/std/net/url"
)

func main() {
	u, err := url.Parse("../../..//search?q=dotnet")
	if err != nil {
		log.Fatal(err)
	}
	base, err := url.Parse("http://example.com/directory/")
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(base.ResolveReference(u))
}
Output:

http://example.com/search?q=dotnet

func (*URL) String

func (u *URL) String() string

Stringは URL を有効なURL文字列に再構築します。 結果の一般的な形式は次のいずれかです:

scheme:opaque?query#fragment scheme://userinfo@host/path?query#fragment

もしu.Opaqueが空でない場合、Stringは最初の形式を使用します。 そうでなければ、2番目の形式を使用します。 ホスト内の非ASCII文字はエスケープされます。 パスを取得するために、Stringはu.EscapedPath()を使用します。

2番目の形式では、以下のルールが適用されます:

  • もしu.Schemeが空なら、scheme:は省略されます。
  • もしu.Userがnilなら、userinfo@は省略されます。
  • もしu.Hostが空なら、host/は省略されます。
  • もしu.Schemeとu.Hostが空であり、u.Userがnilなら、 scheme://userinfo@host/全体が省略されます。
  • もしu.Hostが空でなく、u.Pathが/で始まるなら、 host/pathの形式は独自の/を追加しません。
  • もしu.RawQueryが空なら、?queryは省略されます。
  • もしu.Fragmentが空なら、#fragmentは省略されます。
Example
package main

import (
	"github.com/shogo82148/std/fmt"
	"github.com/shogo82148/std/net/url"
)

func main() {
	u := &url.URL{
		Scheme:   "https",
		User:     url.UserPassword("me", "pass"),
		Host:     "example.com",
		Path:     "foo/bar",
		RawQuery: "x=1&y=2",
		Fragment: "anchor",
	}
	fmt.Println(u.String())
	u.Opaque = "opaque"
	fmt.Println(u.String())
}
Output:

https://me:pass@example.com/foo/bar?x=1&y=2#anchor
https:opaque?x=1&y=2#anchor

func (*URL) UnmarshalBinary added in v1.8.0

func (u *URL) UnmarshalBinary(text []byte) error
Example
package main

import (
	"github.com/shogo82148/std/fmt"
	"github.com/shogo82148/std/log"
	"github.com/shogo82148/std/net/url"
)

func main() {
	u := &url.URL{}
	err := u.UnmarshalBinary([]byte("https://example.org/foo"))
	if err != nil {
		log.Fatal(err)
	}
	fmt.Printf("%s\n", u)
}
Output:

https://example.org/foo

type Userinfo

type Userinfo struct {
	// contains filtered or unexported fields
}

Userinfo型は、URL のユーザー名とパスワードの詳細を不変なカプセル化します。既存のUserinfo値には、ユーザー名が設定されていることが保証されています(RFC 2396で許可されているように、空にすることも可能です)、また、オプションでパスワードも持つことができます。

func User

func User(username string) *Userinfo

Userは、提供されたユーザー名を含む Userinfo を返します パスワードは設定されていません。

func UserPassword

func UserPassword(username, password string) *Userinfo

UserPasswordは提供されたユーザー名とパスワードを含む Userinfo を返します。 この機能は、レガシーウェブサイトでのみ使用するべきです。 RFC 2396は、この方法でUserinfoを解釈することを「推奨されない」と警告しています。 「URIなどで平文で認証情報を渡すことは、ほとんどの場合セキュリティリスクとなっている」と述べています。

func (*Userinfo) Password

func (u *Userinfo) Password() (string, bool)

Passwordは設定されている場合はパスワードを返し、設定されているかどうかも返します。

func (*Userinfo) String

func (u *Userinfo) String() string

Stringは「username [: password]」の標準形式でエンコードされたユーザー情報を返します。

func (*Userinfo) Username

func (u *Userinfo) Username() string

Usernameはユーザー名を返します。

type Values

type Values map[string][]string

Valuesは文字列のキーを値のリストにマップします。 通常、クエリパラメータやフォームの値に使用されます。 http.Headerマップとは異なり、Valuesマップのキーは大文字小文字を区別します。

Example
package main

import (
	"github.com/shogo82148/std/fmt"
	"github.com/shogo82148/std/net/url"
)

func main() {
	v := url.Values{}
	v.Set("name", "Ava")
	v.Add("friend", "Jess")
	v.Add("friend", "Sarah")
	v.Add("friend", "Zoe")
	// v.Encode() == "name=Ava&friend=Jess&friend=Sarah&friend=Zoe"
	fmt.Println(v.Get("name"))
	fmt.Println(v.Get("friend"))
	fmt.Println(v["friend"])
}
Output:

Ava
Jess
[Jess Sarah Zoe]

func ParseQuery

func ParseQuery(query string) (Values, error)

ParseQueryはURLエンコードされたクエリ文字列を解析して、 各キーに指定された値をリストしたマップを返します。 ParseQueryは常に、最初にエンコードできないエラーが見つかった場合を示すnon-nilのマップを返します。エラーの詳細はerrに記載されます。

クエリはアンパサンドで区切られたキー=値のリストとして期待されます。 イコール記号がない設定は、空の値に設定されたキーとして解釈されます。 URLエンコードされていないセミコロンが含まれる設定は無効と見なされます。

Example
m, err := url.ParseQuery(`x=1&y=2&y=3`)
if err != nil {
	log.Fatal(err)
}
fmt.Println(toJSON(m))
Output:

{"x":["1"], "y":["2", "3"]}

func (Values) Add

func (v Values) Add(key, value string)

Addはkeyに値を追加します。keyと関連付けられた既存の値に追加します。

Example
package main

import (
	"github.com/shogo82148/std/fmt"
	"github.com/shogo82148/std/net/url"
)

func main() {
	v := url.Values{}
	v.Add("cat sounds", "meow")
	v.Add("cat sounds", "mew")
	v.Add("cat sounds", "mau")
	fmt.Println(v["cat sounds"])

}
Output:

[meow mew mau]

func (Values) Del

func (v Values) Del(key string)

Delはキーに関連付けられた値を削除します。

Example
package main

import (
	"github.com/shogo82148/std/fmt"
	"github.com/shogo82148/std/net/url"
)

func main() {
	v := url.Values{}
	v.Add("cat sounds", "meow")
	v.Add("cat sounds", "mew")
	v.Add("cat sounds", "mau")
	fmt.Println(v["cat sounds"])

	v.Del("cat sounds")
	fmt.Println(v["cat sounds"])

}
Output:

[meow mew mau]
[]

func (Values) Encode

func (v Values) Encode() string

Encodeは値をキーでソートされた形式で「URLエンコード」します ("bar=baz&foo=quux")

Example
package main

import (
	"github.com/shogo82148/std/fmt"
	"github.com/shogo82148/std/net/url"
)

func main() {
	v := url.Values{}
	v.Add("cat sounds", "meow")
	v.Add("cat sounds", "mew/")
	v.Add("cat sounds", "mau$")
	fmt.Println(v.Encode())

}
Output:

cat+sounds=meow&cat+sounds=mew%2F&cat+sounds=mau%24

func (Values) Get

func (v Values) Get(key string) string

Getは指定したキーに関連付けられた最初の値を返します。 キーに関連付けられた値がない場合、Getは空の文字列を返します。 複数の値にアクセスするには、直接マップを使用してください。

Example
package main

import (
	"github.com/shogo82148/std/fmt"
	"github.com/shogo82148/std/net/url"
)

func main() {
	v := url.Values{}
	v.Add("cat sounds", "meow")
	v.Add("cat sounds", "mew")
	v.Add("cat sounds", "mau")
	fmt.Printf("%q\n", v.Get("cat sounds"))
	fmt.Printf("%q\n", v.Get("dog sounds"))

}
Output:

"meow"
""

func (Values) Has added in v1.17.0

func (v Values) Has(key string) bool

Hasは与えられたキーが設定されているかどうかを確認します。

Example
package main

import (
	"github.com/shogo82148/std/fmt"
	"github.com/shogo82148/std/net/url"
)

func main() {
	v := url.Values{}
	v.Add("cat sounds", "meow")
	v.Add("cat sounds", "mew")
	v.Add("cat sounds", "mau")
	fmt.Println(v.Has("cat sounds"))
	fmt.Println(v.Has("dog sounds"))

}
Output:

true
false

func (Values) Set

func (v Values) Set(key, value string)

Setはキーを値にセットします。既存の値を置き換えます。

Example
package main

import (
	"github.com/shogo82148/std/fmt"
	"github.com/shogo82148/std/net/url"
)

func main() {
	v := url.Values{}
	v.Add("cat sounds", "meow")
	v.Add("cat sounds", "mew")
	v.Add("cat sounds", "mau")
	fmt.Println(v["cat sounds"])

	v.Set("cat sounds", "meow")
	fmt.Println(v["cat sounds"])

}
Output:

[meow mew mau]
[meow]

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL