Go语言教程之边写边学:将结构字段转换为映射字符串

下面的代码片段声明了一个结构类型MyStruct,其中包含字段Name和Score。名为myMap的映射具有字符串键和一个空接口作为创建的值。

示例代码:

package main

import (
	"encoding/json"
	"fmt"
)

type MyStruct struct {
	Name  string
	Score int
}

func main() {
	ms := MyStruct{Name: "John", Score: 34}

	var myMap map[string]interface{}
	data, _ := json.Marshal(ms)
	json.Unmarshal(data, &myMap)

	fmt.Println(myMap["Name"])
	fmt.Println(myMap["Score"])
}

输出:

John
34
Go语言教程之边写边学:使用空接口动态添加结构体成员

示例代码:

package main

import (
	"fmt"
)

type Before struct {
	m string
}

func append(b interface{}) interface{} {
	return struct {
		Before
		n string
	}{b.(Before), "rest"}
}

func main() {
	b := Before{"test"}
	a := append(b)
	fmt.Println(a)
}

输出:

{{test} rest}
Go语言教程之边写边学:初始化包含结构体切片的结构体

示例代码:

package main

import (
	"fmt"
	"math/rand"
)

type LuckyNumber struct {
	number int
}

type Person struct {
	lucky_numbers []LuckyNumber
}

func main() {
	tmp := make([]LuckyNumber, 10)
	for i := range tmp {
		tmp[i].number = rand.Intn(100)
	}
	a := Person{tmp}
	fmt.Println(a)
}

输出:

{[{81} {87} {47} {59} {81} {18} {25} {40} {56} {0}]}
Go语言教程之边写边学:检查结构体中是否存在某个字段

下面的代码片段声明了具有字段A、B和C的结构类型Test。我们需要验证字段Z是否存在于结构类型Test中。

示例代码:

package main

import (
	"log"
	"reflect"
)

func main() {
	type test struct {
		A bool
		B bool
		C bool
	}

	v := new(test)
	metaValue := reflect.ValueOf(v).Elem()

	for _, name := range []string{"A", "C", "Z"} {
		field := metaValue.FieldByName(name)
		if field == (reflect.Value{}) {
			log.Printf("Field %s not exist in struct", name)
		}
	}
}

输出:

2009/11/10 23:00:00 Field Z not exist in struct
Go语言教程之边写边学:golang中创建结构体字典

示例代码:

package main

import "fmt"

type Emp struct {
	x int
	y []string
}

func main() {
	var list = map[string]*Emp{"e1": {1001, []string{"John", "US"}}}

	e := new(Emp)
	e.x = 1002
	e.y = []string{"Rock", "UK"}

	list["e2"] = e

	fmt.Println(list["e1"])
	fmt.Println(list["e2"])
}

 

输出:

&{1001 [John US]}
&{1002 [Rock UK]}
Go语言教程之边写边学:golang中创建结构体切片

示例代码:

package main

import (
	"fmt"
)

type Widget struct {
	id    int
	attrs []string
}

func main() {

	widgets := []Widget{
		Widget{
			id:    10,
			attrs: []string{"blah", "foo"},
		},
		Widget{
			id:    11,
			attrs: []string{"foo", "bar"},
		},
		Widget{
			id:    12,
			attrs: []string{"xyz"},
		},
	}

	for _, j := range widgets {
		fmt.Printf("%d ", j.id)
		for _, y := range j.attrs {
			fmt.Printf(" %s ", y)
		}
		fmt.Println()
	}
}

输出:

10  blah  foo 
11  foo  bar
12  xyz
Go语言教程之边写边学:常用的软件库:结构体和字段验证

包验证器根据标签对结构体和单个字段进行值验证。它具有以下独特的功能,可通过使用验证标记或自定义验证器进行跨字段和跨结构验证。切片、数组和map,允许验证多维字段的任何或所有级别。能够深入研究映射键和值以进行验证。

安装验证包:

go get github.com/go-playground/validator

 

示例代码:

package main

import (
	"fmt"

	"github.com/go-playground/validator"
)

// User contains user information
type User struct {
	FirstName   string `json:"fname" validate:"alpha"`
	LastName    string `json:"lname" validate:"alpha"`
	Age         uint8  `validate:"gte=20,lte=65"`
	Email       string `json:"e-mail" validate:"required,email"`
	JoiningDate string `validate:"datetime"`
}

// use a single instance of Validate, it caches struct info
var validate *validator.Validate

func main() {

	validate = validator.New()

	user := &User{
		FirstName:   "Test25",
		LastName:    "Test",
		Age:         75,
		Email:       "Badger.Smith@",
		JoiningDate: "005-25-10",
	}

	err := validate.Struct(user)
	if err != nil {
		if _, ok := err.(*validator.InvalidValidationError); ok {
			fmt.Println(err)
			return
		}

		fmt.Println("------ List of tag fields with error ---------")

		for _, err := range err.(validator.ValidationErrors) {
			fmt.Println(err.StructField())
			fmt.Println(err.ActualTag())
			fmt.Println(err.Kind())
			fmt.Println(err.Value())
			fmt.Println(err.Param())
			fmt.Println("---------------")
		}
		return
	}
}

 

输出:

------ List of tag fields with error ---------
FirstName
alpha
string
Test25

---------------
Age
lte
uint8
75
65
---------------
Email
email
string
Badger.Smith@

---------------
JoiningDate
datetime
string
005-25-10

---------------
Go语言教程之边写边学:导入导出:如何从其他包或者子包中导入结构体

您将学习如何创建自己的包并导入自定义包。在此示例中,您将看到如何从另一个包或子包导入结构。您还可以从主包调用自定义包的函数。

以下是我们应用程序的目录结构。

├── family
│   ├── go.mod
│   ├── main.go
│   └── father
│       └── father.go
│       └── son
│           └── son.go

进入family目录并运行以下命令以创建一个名为 family 的go模块。

go mod init family

上面的命令将创建一个名为的文件。

 

要使用自定义包,我们必须先导入它。导入路径是附加在包的子目录和包名称上的模块名称。在我们的示例中,模块名称是 family,包父位于family正下方的父文件夹中。并且,包son位于父文件夹下的子文件夹中。

因此,"family/father"将导入father包,类似"family/father/son"将导入son包

package main

import (
	parent "family/father"
	child "family/father/son"

	"fmt"
)

func main() {
	f := new(parent.Father)
	fmt.Println(f.Data("Mr. Jeremy Maclin"))

	c := new(child.Son)
	fmt.Println(c.Data("Riley Maclin"))
}

我们将father包别名为parent,将son别名为child。在main() 函数中,我们现在可以使用上面的别名。

 

在father文件夹中创建一个文件 。father内的文件应以package father开头,因为它属于father包。

# family\father\father.go
package father

import "fmt"

func init() {
	fmt.Println("Father package initialized")
}

type Father struct {
	Name string
}

func (f Father) Data(name string) string {
	f.Name = "Father : " + name
	return f.Name
}

init 函数可用于执行初始化工作,也可用于在执行开始之前确认程序的正确性。

 

在son文件夹中创建一个文件 。son文件夹中的文件应以package son开头,因为它属于 。

# family\father\son\son.go
package son

import "fmt"

func init() {
	fmt.Println("Son package initialized")
}

type Son struct {
	Name string
}

func (s Son) Data(name string) string {
	s.Name = "Son : " + name
	return s.Name
}

 

family>go run main.go

如果运行该程序,将获得以下输出。

Father package initialized
Son package initialized
Father : Mr. Jeremy Maclin
Son : Riley Maclin

 

Go语言教程之边写边学:结构 struct

结构是具有声明数据类型的数据字段的集合。Golang能够通过组合一个或多个类型(包括内置类型和用户定义类型)来声明和创建自己的数据类型。结构中的每个数据字段都使用已知类型声明,该类型可以是内置类型或其他用户定义类型。

结构是在Golang中创建具体的用户定义类型的唯一方法。结构类型是通过组合一组固定的唯一字段来声明的。结构可以提高模块化,并允许在系统周围创建和传递复杂的数据结构。您还可以将结构视为创建数据记录(如员工记录或电子商务产品)的模板。

声明以关键字type开头,然后是新结构的名称,最后是关键字struct。在大括号内,使用名称和类型指定了一系列数据字段。

type identifier struct{
  field1 data_type
  field2 data_type
  field3 data_type
}

 

结构类型的声明

声明了一个结构类型矩形,该rectangle具有三个不同数据类型的数据字段。在这里,使用的结构不实例化该类型的新实例。

package main
 
import "fmt"
 
type rectangle struct {
	length  float64
	breadth float64
	color   string
}
 
func main() {
	fmt.Println(rectangle{10.5, 25.10, "red"})
}

rectangle结构及其字段不会导出到其他包,因为标识符以小写字母开头。在Golang中,如果名称以大写字母开头,则标识符将导出到其他包中,否则可访问性将仅在包内受到限制。

 

创建结构类型的实例

var关键字初始化变量rect。使用表示法,将值分配给结构字段。

package main
 
import "fmt"
 
type rectangle struct {
	length  int
	breadth int
	color   string
 
	geometry struct {
		area      int
		perimeter int
	}
}
 
func main() {
	var rect rectangle
	rect.length = 10
	rect.breadth = 20
	rect.color = "Green"
 
	rect.geometry.area = rect.length * rect.breadth
	rect.geometry.perimeter = 2 * (rect.length + rect.breadth)
 
	fmt.Println(rect)
	fmt.Println("Area:\t", rect.geometry.area)
	fmt.Println("Perimeter:", rect.geometry.perimeter)
}

结构将打印到终端,显示已分配值。

 

创建结构实例

通过使用结构文本并为结构的字段赋值来创建rectangle结构的实例。

package main

import "fmt"

type rectangle struct {
	length  int
	breadth int
	color   string
}

func main() {
	var rect1 = rectangle{10, 20, "Green"}
	fmt.Println(rect1)

	var rect2 = rectangle{length: 10, color: "Green"}
	fmt.Println(rect2)

	rect3 := rectangle{10, 20, "Green"}
	fmt.Println(rect3)

	rect4 := rectangle{length: 10, breadth: 20, color: "Green"}
	fmt.Println(rect4)

	rect5 := rectangle{breadth: 20, color: "Green"}
	fmt.Println(rect5)
}

 

使用 new 关键字的结构实例化

还可以使用new关键字创建结构的实例。然后可以使用点表示法将数据值分配给数据字段。

package main
 
import "fmt"
 
type rectangle struct {
	length  int
	breadth int
	color   string
}
 
func main() {
	rect1 := new(rectangle) // rect1是指针
	rect1.length = 10
	rect1.breadth = 20
	rect1.color = "Green"
	fmt.Println(rect1)
 
	var rect2 = new(rectangle) // rect2是实例对象
	rect2.length = 10
	rect2.color = "Red"
	fmt.Println(rect2)
}

实例化矩形结构的两个实例,rect1 指向实例化结构的地址,rect2是它所表示的结构的名称。

 

使用指针地址运算符的结构实例化

使用指针地址创建rectangle结构的实例运算符&符号表示。

package main

import "fmt"

type rectangle struct {
	length  int
	breadth int
	color   string
}

func main() {
	var rect1 = &rectangle{10, 20, "Green"} // 不能省略任何属性值
	fmt.Println(rect1)

	var rect2 = &rectangle{}
	rect2.length = 10
	rect2.color = "Red"
	fmt.Println(rect2)// breadth没有赋值

	var rect3 = &rectangle{}
	(*rect3).breadth = 10
	(*rect3).color = "Blue"
	fmt.Println(rect3)// length没有赋值
}

 

嵌套结构类型

可以通过使用其他结构类型作为结构字段的类型来创建结构类型来嵌套结构。将一个结构嵌套在另一个结构中可能是对更复杂的结构进行建模的有用方法。

package main

import "fmt"

type Salary struct {
	Basic, HRA, TA float64
}

type Employee struct {
	FirstName, LastName, Email string
	Age                        int
	MonthlySalary              []Salary
}

func main() {
	e := Employee{
		FirstName: "Mark",
		LastName:  "Jones",
		Email:     "mark@gmail.com",
		Age:       25,
		MonthlySalary: []Salary{
			Salary{
				Basic: 15000.00,
				HRA:   5000.00,
				TA:    2000.00,
			},
			Salary{
				Basic: 16000.00,
				HRA:   5000.00,
				TA:    2100.00,
			},
			Salary{
				Basic: 17000.00,
				HRA:   5000.00,
				TA:    2200.00,
			},
		},
	}
	fmt.Println(e.FirstName, e.LastName)
	fmt.Println(e.Age)
	fmt.Println(e.Email)
	fmt.Println(e.MonthlySalary[0])
	fmt.Println(e.MonthlySalary[1])
	fmt.Println(e.MonthlySalary[2])
}

 

在结构类型定义中使用字段标记

声明结构时,可以用``字段标记定义对应的字段字符串。

package main
 
import (
    "fmt"
    "encoding/json"
)
 
type Employee struct {
    FirstName  string `json:"firstname"`
    LastName   string `json:"lastname"`
    City string `json:"city"`
}
 
func main() {
    json_string := `
    {
        "firstname": "Rocky",
        "lastname": "Sting",
        "city": "London"
    }`
 
    emp1 := new(Employee)
    json.Unmarshal([]byte(json_string), emp1)
    fmt.Println(emp1)
 
    emp2 := new(Employee)
    emp2.FirstName = "Ramesh"
    emp2.LastName = "Soni"
    emp2.City = "Mumbai"
    jsonStr, _ := json.Marshal(emp2)
    fmt.Printf("%s\n", jsonStr)
}

标记表示为原始字符串值(包装在一对``中),并由正常代码执行忽略。

 

将方法添加到结构类型

还可以使用接收器将方法添加到结构类型。将方法EmpInfo添加到Employee结构中。

package main

import "fmt"

type Salary struct {
	Basic, HRA, TA float64
}

type Employee struct {
	FirstName, LastName, Email string
	Age                        int
	MonthlySalary              []Salary
}

func (e Employee) EmpInfo() string {
	fmt.Println(e.FirstName, e.LastName)
	fmt.Println(e.Age)
	fmt.Println(e.Email)
	for _, info := range e.MonthlySalary {
		fmt.Println("===================")
		fmt.Println(info.Basic)
		fmt.Println(info.HRA)
		fmt.Println(info.TA)
	}
	return "----------------------"
}

func main() {

	e := Employee{
		FirstName: "Mark",
		LastName:  "Jones",
		Email:     "mark@gmail.com",
		Age:       25,
		MonthlySalary: []Salary{
			Salary{
				Basic: 15000.00,
				HRA:   5000.00,
				TA:    2000.00,
			},
			Salary{
				Basic: 16000.00,
				HRA:   5000.00,
				TA:    2100.00,
			},
			Salary{
				Basic: 17000.00,
				HRA:   5000.00,
				TA:    2200.00,
			},
		},
	}

	fmt.Println(e.EmpInfo())
}

 

为结构字段分配默认值

分配自定义默认值的方法可以通过使用构造函数来实现。Info函数可用于创建具有name和age字段的自定义默认值的结构,而不是直接创建结构。

package main

import "fmt"

type Employee struct {
	Name string
	Age  int
}

func (obj *Employee) Info() {
	if obj.Name == "" {
		obj.Name = "John Doe"
	}
	if obj.Age == 0 {
		obj.Age = 25
	}
}

func main() {
	emp1 := Employee{Name: "Mr. Fred"}
	emp1.Info()
	fmt.Println(emp1)

	emp2 := Employee{Age: 26}
	emp2.Info()
	fmt.Println(emp2)
}

这是一种技术,而不是 Golang 规范的一部分。

 

查找结构类型

reflect包支持检查结构的基础类型。

package main

import (
	"fmt"
	"reflect"
)

type rectangle struct {
	length  float64
	breadth float64
	color   string
}

func main() {
	var rect1 = rectangle{10, 20, "Green"}
	fmt.Println(reflect.TypeOf(rect1))         // main.rectangle
	fmt.Println(reflect.ValueOf(rect1).Kind()) // struct

	rect2 := rectangle{length: 10, breadth: 20, color: "Green"}
	fmt.Println(reflect.TypeOf(rect2))         // main.rectangle
	fmt.Println(reflect.ValueOf(rect2).Kind()) // struct

	rect3 := new(rectangle)
	fmt.Println(reflect.TypeOf(rect3))         // *main.rectangle
	fmt.Println(reflect.ValueOf(rect3).Kind()) // ptr

	var rect4 = &rectangle{}
	fmt.Println(reflect.TypeOf(rect4))         // *main.rectangle
	fmt.Println(reflect.ValueOf(rect4).Kind()) // ptr
}

 

将结构与分配给数据字段的不同值进行比较

可以使用比较运算符比较相同类型的结构。

package main

import "fmt"

type rectangle struct {
	length  float64
	breadth float64
	color   string
}

func main() {
	var rect1 = rectangle{10, 20, "Green"}
	rect2 := rectangle{length: 20, breadth: 10, color: "Red"}

	if rect1 == rect2 {
		fmt.Println("True")
	} else {
		fmt.Println("False")
	}

	rect3 := new(rectangle)
	var rect4 = &rectangle{}

	if rect3 == rect4 {
		fmt.Println("True")
	} else {
		fmt.Println("False")
	}
}

 

使用值和指针引用复制结构类型

r2将与r1相同,它是R1的副本而不是对它的引用。 对r2所做的任何更改都不会应用于r1,反之亦然。更新r3时,分配给r1的基础内存也会更新。

package main

import "fmt"

type rectangle struct {
	length  float64
	breadth float64
	color   string
}

func main() {
	r1 := rectangle{10, 20, "Green"}
	fmt.Println(r1)

	r2 := r1
	r2.color = "Pink"
	fmt.Println(r2)

	r3 := &r1
	r3.color = "Red"
	fmt.Println(r3)

	fmt.Println(r1)
}

输出

{10 20 Green}
{10 20 Pink}
&{10 20 Red}
{10 20 Red}

由于r1和r3都引用相同的底层内存,因此它们的值是相同的。打印r3和r1的值显示值相同。

  • 当前日期:
  • 北京时间:
  • 时间戳:
  • 今年的第:18周
  • 我的 IP:18.116.118.216
农历
五行
冲煞
彭祖
方位
吉神
凶神
极简任务管理 help
+ 0 0 0
Task Idea Collect