TopGit theo dõi go-playground/form trên GitHub, đã đạt 922 sao. :steam_locomotive: Decodes url.Values into Go value(s) and Encodes Go value(s) into url.Values. Dual Array and Full map support.
Tóm tắt dựng từ metadata GitHub của chính dự án — chưa có bài review TopGit. Trang sẽ tự động cập nhật khi bài review đầy đủ được xuất bản.
VÌ SAO CHƯA CÓ REVIEW
TopGit viết bài đầy đủ cho repo có nhiều sao nhất và được yêu cầu nhiều nhất. Trang này là snapshot trong thời gian chờ — xem README gốc ở tab READ ME.
Package form Decodes url.Values into Go value(s) and Encodes Go value(s) into url.Values.
It has the following features:
Supports map of almost all types.
Supports both Numbered and Normal arrays eg. "Array[0]" and just "Array" with multiple values passed.
Slice honours the specified index. eg. if "Slice[2]" is the only Slice value passed down, it will be put at index 2; if slice isn't big enough it will be expanded.
Array honours the specified index. eg. if "Array[2]" is the only Array value passed down, it will be put at index 2; if array isn't big enough a warning will be printed and value ignored.
Only creates objects as necessary eg. if no array or map values are passed down, the array and map are left as their default values in the struct.
Allows for Custom Type registration.
Handles time.Time using RFC3339 time format by default, but can easily be changed by registering a Custom Type, see below.
Handles Encoding & Decoding of almost all Go types eg. can Decode into struct, array, map, int... and Encode a struct, array, map, int...
Common Questions
Does it support encoding.TextUnmarshaler? No because TextUnmarshaler only accepts []byte but posted values can have multiple values, so is not suitable.
Mixing array/slice with array[idx]/slice[idx], in which order are they parsed? array/slice then array[idx]/slice[idx]
Supported Types ( out of the box )
string
bool
int, int8, int16, int32, int64
uint, uint8, uint16, uint32, uint64
float32, float64
struct and anonymous struct
interface{}
time.Time - by default using RFC3339
a pointer to one of the above types
slice, array
map
custom types can override any of the above types
many other types may be supported inherently
NOTE: map, struct and slice nesting are ad infinitum.
Installation
Use go get.
go get github.com/go-playground/form
Then import the form package into your own code.
import "github.com/go-playground/form/v4"
Usage
Use symbol . for separating fields/structs. (eg. structfield.field)
Use [index or key] for access to index of a slice/array or key for map. (eg. arrayfield[0], mapfield[keyvalue])
package main
import (
"fmt"
"log"
"net/url"
"github.com/go-playground/form/v4"
)
// Address contains address information
type Address struct {
Name string
Phone string
}
// User contains user information
type User struct {
Name string
Age uint8
Gender string
Address []Address
Active bool `form:"active"`
MapExample map[string]string
NestedMap map[string]map[string]string
NestedArray [][]string
}
// use a single instance of Decoder, it caches struct info
var decoder *form.Decoder
func main() {
decoder = form.NewDecoder()
// this simulates the results of http.Request's ParseForm() function
values := parseForm()
var user User
// must pass a pointer
err := decoder.Decode(&user, values)
if err != nil {
log.Panic(err)
}
fmt.Printf("%#v\n", user)
}
// this simulates the results of http.Request's ParseForm() function
func parseForm() url.Values {
return url.Values{
"Name": []string{"joeybloggs"},
"Age": []string{"3"},
"Gender": []string{"Male"},
"Address[0].Name": []string{"26 Here Blvd."},
"Address[0].Phone": []string{"9(999)999-9999"},
"Address[1].Name": []string{"26 There Blvd."},
"Address[1].Phone": []string{"1(111)111-1111"},
"active": []string{"true"},
"MapExample[key]": []string{"value"},
"NestedMap[key][key]": []string{"value"},
"NestedArray[0][0]": []string{"value"},
}
}
Encoding
package main
import (
"fmt"
"log"
"github.com/go-playground/form/v4"
)
// Address contains address information
type Address struct {
Name string
Phone string
}
// User contains user information
type User struct {
Name string
Age uint8
Gender string
Address []Address
Active bool `form:"active"`
MapExample map[string]string
NestedMap map[string]map[string]string
NestedArray [][]string
}
// use a single instance of Encoder, it caches struct info
var encoder *form.Encoder
func main() {
encoder = form.NewEncoder()
user := User{
Name: "joeybloggs",
Age: 3,
Gender: "Male",
Address: []Address{
{Name: "26 Here Blvd.", Phone: "9(999)999-9999"},
{Name: "26 There Blvd.", Phone: "1(111)111-1111"},
},
Active: true,
MapExample: map[string]string{"key": "value"},
NestedMap: map[string]map[string]string{"key": {"key": "value"}},
NestedArray: [][]string{{"value"}},
}
// must pass a pointer
values, err := encoder.Encode(&user)
if err != nil {
log.Panic(err)
}
fmt.Printf("%#v\n", values)
}
ADDITIONAL: if a struct type is registered, the function will only be called if a url.Value exists for
the struct and not just the struct fields eg. url.Values{"User":"Name%3Djoeybloggs"} will call the
custom type function with 'User' as the type, however url.Values{"User.Name":"joeybloggs"} will not.
you can tell form to ignore fields using - in the tag
type MyStruct struct {
Field string `form:"-"`
}
Omitempty
you can tell form to omit empty fields using ,omitempty or FieldName,omitempty in the tag
type MyStruct struct {
Field string `form:",omitempty"`
Field2 string `form:"CustomFieldName,omitempty"`
}
Notes
To maximize compatibility with other systems the Encoder attempts
to avoid using array indexes in url.Values if at all possible.
eg.
// A struct field of
Field []string{"1", "2", "3"}
// will be output a url.Value as
"Field": []string{"1", "2", "3"}
and not
"Field[0]": []string{"1"}
"Field[1]": []string{"2"}
"Field[2]": []string{"3"}
// however there are times where it is unavoidable, like with pointers
i := int(1)
Field []*string{nil, nil, &i}
// to avoid index 1 and 2 must use index
"Field[2]": []string{"1"}
Benchmarks
Run on M1 MacBook Pro using go version go1.20.6 darwin/amd64
NOTE: the 1 allocation and B/op in the first 4 decodes is actually the struct allocating when passing it in, so primitives are actually zero allocation.
This package is aligned with the Go release policy in that support is guaranteed for
the two most recent major versions.
This does not mean the package will not work with older versions of Go, only that we reserve the right to increase the
MSGV(Minimum Supported Go Version) when the need arises to address Security issues/patches, OS issues & support or newly
introduced functionality that would greatly benefit the maintenance and/or usage of this package.
If and when the MSGV is increased it will be done so in a minimum of a Minor release bump.
Complimentary Software
Here is a list of software that compliments using this library post decoding.
Validator - Go Struct and Field validation, including Cross Field, Cross Struct, Map, Slice and Array diving.
mold - Is a general library to help modify or set data within data structures and other objects.
License
Distributed under MIT License, please see license file in code for more details.
Trang TopGit này là một snapshot — tab "Readme" hiển thị nguyên văn README của repo (đã bỏ link, giữ ảnh). Repo GitHub ở github.com/go-playground/form là nguồn chính thức.
go-playground/form có những chủ đề gì?
GitHub topics của go-playground/form: "decoding", "encoder", "form", "form-data", "parser". TopGit xếp repo vào nhóm mã nguồn mở.
go-playground/form có phải mã nguồn mở không?
Có — go-playground/form phát hành theo license MIT, nghĩa là mã nguồn mở để đọc, fork và (tùy license) tái sử dụng. Mã: github.com/go-playground/form.
go-playground/form có website riêng không?
TopGit chưa ghi nhận URL trang chủ cho go-playground/form. Phần README ở tab phía trên thường có link demo, hoặc xem mô tả GitHub của repo.
go-playground/form còn đang phát triển không?
Commit gần nhất trên go-playground/form là 10 tháng trước (theo timestamp GitHub). Repo có 47 fork — một chỉ báo về mức độ quan tâm của cộng đồng.
go-playground/form dùng license gì?
go-playground/form phát hành theo license MIT. Nên mở file LICENSE trên GitHub để xác nhận — license metadata đôi khi lệch với thực tế dự án.
Đọc đầy đủ README ở tab phía trên.
Muốn nghe thêm một ý kiến về form?
Hỏi một AI đọc được trang này — một cú bấm là có ngay nhận định về form.