1.打印数据的类型2. 字典(键值对,map)3. 错误处理4. 结构体(struct) 和方法(methods)5.接口(interfaces)6. 时间
1.打印数据的类型package main
import (
"fmt"
"reflect"
)
func main() {
str2 := "Go语言"
fmt.Println(reflect.TypeOf(str2[2]).Kind()) // uint8
}
reflect.TypeOf().Kind() 可以知道某个变量的类型
2. 字典(键值对,map)map 类似于 java 的 HashMap,Python的字典(dict),是一种存储键值对(Key-Value)的数据解构。使用方式和其他语言几乎没有区别。
// 仅声明
m1 := make(map[string]int)
// 声明时初始化
m2 := map[string]string{
"Sam": "Male",
"Alice": "Female",
}
// 赋值/修改
m1["Tom"] = 18
3. 错误处理
果函数实现过程中,出现不能处理的错误,可以返回给调用者处理。比如我们调用标准库函数os.Open读取文件,os.Open 有2个返回值,第一个是 *File,第二个是 error, 如果调用成功,error 的值是 nil,如果调用失败,例如文件不存在,我们可以通过 error 知道具体的错误信息。
import (
"fmt"
"os"
)
func main() {
_, err := os.Open("filename.txt")
if err != nil {
fmt.Println(err)
}
}
// open filename.txt: no such file or directory
4. 结构体(struct) 和方法(methods)
可以在结构体中定义多个字段,为结构体实现方法,实例化等。接下来我们定义一个结构体 Student,并为 Student 添加 name,age 字段,并实现 hello() 方法。
type Student struct {
name string
age int
}
func (stu *Student) hello(person string) string {
return fmt.Sprintf("hello %s, I am %s", person, stu.name)
}
func main() {
stu := &Student{
name: "Tom",
}
msg := stu.hello("Jack")
fmt.Println(msg) // hello Jack, I am Tom
}
使用 Student{field: value, …}的形式创建 Student 的实例,字段不需要每个都赋值,没有显性赋值的变量将被赋予默认值,例如 age 将被赋予默认值 0。实现方法与实现函数的区别在于,func 和函数名hello 之间,加上该方法对应的实例名 stu 及其类型 *Student,可以通过实例名访问该实例的字段name和其他方法了。调用方法通过 实例名.方法名(参数) 的方式。
除此之外,还可以使用 new 实例化:
func main() {
stu2 := new(Student)
fmt.Println(stu2.hello("Alice")) // hello Alice, I am , name 被赋予默认值""
}
5.接口(interfaces)
接口定义了一组方法的集合,接口不能被实例化,一个类型可以实现多个接口。
举一个简单的例子,定义一个接口 Person和对应的方法 getName() 和 getAge():
type Person interface {
getName() string
}
type Student struct {
name string
age int
}
func (stu *Student) getName() string {
return stu.name
}
func main() {
var p Person = &Student{
name: "Tom",
age: 18,
}
fmt.Println(p.getName()) // Tom
}
Go 语言中,并不需要显式地声明实现了哪一个接口,只需要直接实现该接口对应的方法即可。实例化 Student后,强制类型转换为接口类型 Person。
如果 Student 没有完全实现 Person 的方法,比如我们将 (*Student).getName() 删掉,编译时会出现如下报错信息。
*Student does not implement Person (missing getName method)
因为我们并没有在 main 函数中使用。这种情况下我们如何确保某个类型实现了某个接口的所有方法呢?一般可以使用下面的方法进行检测,如果实现不完整,编译期将会报错。
var _ Person = (*Student)(nil)
将空值 nil 转换为 *Student 类型,再转换为 Person 接口,如果转换失败,说明 Student 并没有实现 Person 接口的所有方法。
实例可以强制类型转换为接口,接口也可以强制类型转换为实例。
func main() {
var p Person = &Student{
name: "Tom",
age: 18,
}
stu := p.(*Student) // 接口转为实例
fmt.Println(stu.getAge())
}
6. 时间
package utils
import (
"fmt"
"testing"
"time"
)
func TestNow(t *testing.T) {
//返回现在时间 Time 时间类型
timeNow := time.Now() //2022-02-27 04:02:23.161826209 +0000 UTC m=+0.000658752
fmt.Println("now:{}", timeNow)
}
// 将时间转换成 string
func TestTime2String(t *testing.T) {
timeNow := time.Now()
timeString := timeNow.Format("2006-01-02 15:04:05") //2015-06-15 08:52:32
fmt.Println("time now str:", timeString)
}
// 获取时间戳,并将时间戳转换成Time string
func TestUnixTime(t *testing.T) {
//获取时间戳
timestamp := time.Now().Unix() //1645934754
fmt.Println("当前的时间戳:", timestamp)
//时间戳转Time
timestamp = 0
timeNow := time.Unix(timestamp, 0) //2017-08-30 16:19:19 +0800 CST
// 再转 string
timeString := timeNow.Format("2006-01-02 15:04:05") //2015-06-15 08:52:32
fmt.Println("时间戳转换成string:", timeString)
}
// 将string 转换成时间
func Test2(t *testing.T) {
stringTime := "2017-08-30 16:40:41"
stringTime = "dasd"
loc, _ := time.LoadLocation("Local")
the_time, err := time.ParseInLocation("2006-01-02 15:04:05", stringTime, loc)
if err == nil {
unix_time := the_time.Unix() //1504082441
fmt.Println(unix_time)
} else {
timeNow := time.Unix(0, 0) //1970-01-01 00:00:00
timeString := timeNow.Format("2006-01-02 15:04:05") //2015-06-15 08:52:32
fmt.Println("begin:", timeString)
}
}



