最近研究钉钉机器人的时候,总是会向钉钉官方接口发送很多请求,发送请求的时候,需要封装body结构体传递参数,还要封装response结构体用来接收返回值,有时候,response结构体中还要嵌套一些结构体,这些结构体大多知识在请求的时候能用到,到了其他位置则是没有任何用途。 在声明了一个又一个的结构体后,我发现,这是一个很麻烦的事情,首先是代码很多,显得有点乱,其次是,结构体直接跳转的时候也不是很方便。 然后我们了解了匿名结构体和结构体嵌套,下面来一起看看吧。
具体实现先看一个没有匿名结构体和结构体嵌套的代码。
//批量获取考勤组
func GetAttendancesGroups(token string, offset int, size int) (groups []dingding.DingAttendGroup, err error) {
var client *http.Client
var request *http.Request
var resp *http.Response
var body []byte
URL := "https://oapi.dingtalk.com/topapi/attendance/getsimplegroups?access_token=" + token
client = &http.Client{Transport: &http.Transport{ //对客户端进行一些配置
TLSClientConfig: &tls.Config{
InsecureSkipVerify: true,
},
}, Timeout: time.Duration(time.Second * 5)}
//此处是post请求的请求题,我们先初始化一个对象
b := BodyGetAttendancesGroups{
Offset: offset,
Size: size,
}
//然后把结构体对象序列化一下
bodymarshal, err := json.Marshal(&b)
if err != nil {
return
}
//再处理一下
reqBody := strings.NewReader(string(bodymarshal))
//然后就可以放入具体的request中的
request, err = http.NewRequest(http.MethodPost, URL, reqBody)
if err != nil {
return
}
resp, err = client.Do(request)
if err != nil {
return
}
defer resp.Body.Close()
body, err = ioutil.ReadAll(resp.Body) //把请求到的body转化成byte[]
if err != nil {
return
}
r := ResponseGetAttendancesGroups{}
//把请求到的结构反序列化到专门接受返回值的对象上面
err = json.Unmarshal(body, &r)
if err != nil {
return
}
if r.Errcode != 0 {
return nil, errors.New("token有误,尝试输入新token")
}
// 此处举行具体的逻辑判断,然后返回即可
r.Result.Groups = groups
return groups, nil
}
//传递body参数的结构体
type BodyGetAttendancesGroups struct {
Offset int `json:"offset"`
Size int `json:"size"`
}
//接收response返回值的结构体
type ResponseGetAttendancesGroups struct {
Errcode int `json:"errcode"`
Result ResultGetAttendancesGroups `json:"result"`
}
type ResultGetAttendancesGroups struct {
Groups []DingAttendGroup `json:"groups"`
}
type DingAttendGroup struct {
GroupId int `json:"group_id"` //考勤组id
GroupName string `json:"group_name"` //考勤组名称
MemberCount int `json:"member_count"` //参与考勤人员总数
WorkDayList []string `json:"work_day_list"` //0表示休息,数组内的值,从左到右依次代表周日到周六,每日的排班情况。
ClassesList []string `json:"classes_list"` // 一周的班次时间展示列表
SelectedClass []struct {
Setting struct {
PermitLateMinutes int `json:"permit_late_minutes"` //允许迟到时长
} `json:"setting"`
Sections []struct {
Times []struct {
CheckTime string `json:"check_time"` //打卡时间
CheckType string `json:"check_type"` //打卡类型
} `json:"times"`
} `json:"sections"`
} `json:"selected_class"`
}
上面的代码其实不是我最初的原版代码,可以最后一个结构体,其实我已经使用了嵌套结构体,把很多的结构体,全部写在一起,这样的话,组成一个大大的结构体,代码就不会显得冗余了,所有有关系的结构体都被紧紧的绑定在了一起。上面就是结构体嵌套的好处。
除了结构体嵌套,还有就是匿名结构体,匿名结构体的意思就是,没有具体名称的结构体,用途就是,只使用一次,后续其他地方也用不到了。 这不就完全符合用来接收钉钉官方接口返回的参数,出了这个接口请假内部就再也用不到了。 所有下方代码,就是使用结构体嵌套和匿名结构体后的代码,能够封装一个很强的网络请求,所有需要的结构体全部都封装在一个方法里面。
//此结构体是公用的,需要定义在外面
type DingAttendGroup struct {
GroupId int `json:"group_id"` //考勤组id
GroupName string `json:"group_name"` //考勤组名称
MemberCount int `json:"member_count"` //参与考勤人员总数
WorkDayList []string `json:"work_day_list"` //0表示休息,数组内的值,从左到右依次代表周日到周六,每日的排班情况。
ClassesList []string `json:"classes_list"` // 一周的班次时间展示列表
SelectedClass []struct {
Setting struct {
PermitLateMinutes int `json:"permit_late_minutes"` //允许迟到时长
} `json:"setting"`
Sections []struct {
Times []struct {
CheckTime string `json:"check_time"` //打卡时间
CheckType string `json:"check_type"` //打卡类型
} `json:"times"`
} `json:"sections"`
} `json:"selected_class"`
}
//此结构体是公用的,需要定义在外面
type DingResponseCommon struct {
Errcode int `json:"errcode"`
Errmsg string `json:"errmsg"`
}
//批量获取考勤组
func (a *DingAttendGroup) GetAttendancesGroups(token string, offset int, size int) (groups []DingAttendGroup, err error) {
var client *http.Client
var request *http.Request
var resp *http.Response
var body []byte
URL := "https://oapi.dingtalk.com/topapi/attendance/getsimplegroups?access_token=" + token
client = &http.Client{Transport: &http.Transport{ //对客户端进行一些配置
TLSClientConfig: &tls.Config{
InsecureSkipVerify: true,
},
}, Timeout: time.Duration(time.Second * 5)}
//此处是post请求的请求题,我们先初始化一个匿名结构体对象
b := struct {
Offset int
Size int
}{
Offset: offset,
Size: size,
}
//然后把结构体对象序列化一下
bodymarshal, err := json.Marshal(&b)
if err != nil {
return
}
//再处理一下
reqBody := strings.NewReader(string(bodymarshal))
//然后就可以放入具体的request中的
request, err = http.NewRequest(http.MethodPost, URL, reqBody)
if err != nil {
return
}
resp, err = client.Do(request)
if err != nil {
return
}
defer resp.Body.Close()
body, err = ioutil.ReadAll(resp.Body) //把请求到的body转化成byte[]
if err != nil {
return
}
//初始化一个匿名结构体对象,里面使用了结构体嵌套
r := struct {
DingResponseCommon
Result struct {
Groups []DingAttendGroup `json:"groups"`
} `json:"result"`
}{}
//把请求到的结构反序列化到专门接受返回值的对象上面
err = json.Unmarshal(body, &r)
if err != nil {
return
}
if r.Errcode != 0 {
return nil, errors.New("token有误,尝试输入新token")
}
// 此处举行具体的逻辑判断,然后返回即可
r.Result.Groups = groups
return groups, nil
}
好了,这是一个写了很久代码之后,才发现的好方法,希望能帮到你,感谢批评指正。