struct.go
func newStructType(t reflect.Type, c map[reflect.Type]*structType) *structType {
	if s := c[t]; s != nil {
		return s
	}

	n := t.NumField()
	s := &structType{
		fields:       make([]structField, 0, n),
		fieldsByName: make(map[string]*structField),
	}
	c[t] = s

	for i := 0; i != n; i++ {
		ft := t.Field(i)

		if ft.Anonymous || len(ft.PkgPath) != 0 { // anonymous or non-exported
			continue
		}

		sf := makeStructField(ft, c)

		if sf.name == "-" { // skip
			continue
		}

		s.fields = append(s.fields, sf)
		s.fieldsByName[sf.name] = &s.fields[len(s.fields)-1]
	}

	return s
}
func newStructType(t reflect.Type, c map[reflect.Type]*structType) *structType {
	if s := c[t]; s != nil {
		return s
	}

	n := t.NumField()
	s := &structType{
		fields:       make([]structField, 0, n),
		fieldsByName: make(map[string]*structField),
	}
	c[t] = s

	for i := 0; i != n; i++ {
		ft := t.Field(i)

		if ft.Anonymous || len(ft.PkgPath) != 0 { // anonymous or non-exported
			continue
		}

		sf := makeStructField(ft, c)

		if sf.name == "-" { // skip
			continue
		}

		s.fields = append(s.fields, sf)
		s.fieldsByName[sf.name] = &s.fields[len(s.fields)-1]
	}

	return s
}
// newStructType takes a Go type as argument and extract information to make a
// new structType value.
// The type has to be a struct type or a panic will be raised.