Core: The function is first-class citizen
Simple log printing scenario
type User struct {
Name string
Age int
}
func main() {
user := &User{Name: "Jack", Age: 18}
log.Printf("debug level. user:%v\n",user)
}
Copy the code
Json.marshal () should be used first for each scenario, assuming that different scenarios require different log formats. For example, scenarios A,B, and C require JSON. The following
func main() {
user := &User{Name: "Jack", Age: 18}
s, _ := json.Marshal(user)
log.Printf("user:%v\n",string(s))
}
Copy the code
There is an object-oriented approach, where the User implements a JsonString() method. But today, I’m going to do func
First-class citizen func to do something
So let’s write a function like this
func Debug(user *User) {
s, _ := json.Marshal(user)
log.Printf("debug level. user:%v\n",string(s))
}
Copy the code
Instead of calling the Debug method directly, you define another function, a list of parameters that can hold the Debug function, as follows
type User struct {
Name string
Age int
}
func LogUserData(user *User, fun func(u *User)) {
fun(user)
}
func main() {
user := &User{Name: "Jack", Age: 18}
LogUserData(user,DebugJson)
}
func DebugJson(user *User) {
s, _ := json.Marshal(user)
log.Printf("debug level. user:%v\n",string(s))
}
Copy the code
One advantage of this is that the framework for logging printing is defined, leaving the details of logging printing externally, thus ensuring the ability to extend changes. Second, if all log printing needs to add some common pre – or post-actions, you can add them to LogUserData, so as to avoid the repeated work of adding pre – and post-conditions in various scenarios by directly calling the DebugJson method. In addition, if different action implementation details have different pre – or post-actions, they can be added in the action implementation function. For example, I need to add an Error level log printing method, and the Error log needs SMS to inform me of the Error of the system, so I can directly expand it
Func LogUserData(user * user, fun func(u * user)) {"Start printing log") fun(user) // common after log.printf ("Log printing completed")} func Error(user * user) {// special prefix // send SMSdo Something...
log.Printf("error level. user:%v\n",user)
}
Copy the code
Second, fun’s parameter list doesn’t have to be the same as User’s, as long as it has some relevance, such as redefining a function that judges minors
func IsAdult(user *User, fun func(age int) bool )bool {
return fun(user.Age)
}
func main() {
user := &User{Name: "Jack", Age: 18}
b := IsAdult(user, JudgeAdult)
fmt.Println(b)
}
func JudgeAdult(age int) bool {
if age >= 18 {
return true
}
return false
}
Copy the code
conclusion
The method above is called func(body obj, action func), also known as FUNC (message obj, message consumption action func), which I call a consumption function, and is widely used in Golang, such as NET/HTTP
func HandleFunc(pattern string, handler func(ResponseWriter, *Request)) {
DefaultServeMux.HandleFunc(pattern, handler)
}
Copy the code
The main approach is to use a framework function called func that takes the body, and then receives the action that acts on the body, and uses that action to do some kind of processing on the body. That’s what it looks like graphically
Golang Net/HTTP HandleFunc, for example, defines only the framework for sending and receiving HTTP requests, leaving it up to the outside world to define how to handle requests and what to respond to.
In fact, this is the idea of section. In a process, the main body and the processing process of the main body are cut off, and the processing process is handed over to the external implementation, so that the process has higher flexibility and expansibility.
Attach all code
package main
import (
"encoding/json"
"log"
"fmt"
)
typeFunc LogUserData(User *User, fun func(u *User)) {log.printf (struct {Name string Age int})"Start printing log") fun(user) // common after log.printf ("Log printing completed"} // adult (user * user, fun func(age int) bool)bool {adult (user * user, fun func(age int) bool)boolreturn fun(user.Age)
}
func main() {
user := &User{Name: "Jack", Age: 18}
LogUserData(user,DebugJson)
LogUserData(user,Info)
LogUserData(user,Error)
b := IsAdult(user, JudgeAdult)
fmt.Println(b)
}
func JudgeAdult(age int) bool {
if age >= 18 {
return true
}
return false
}
func DebugJson(user *User) {
s, _ := json.Marshal(user)
log.Printf("debug level. user:%v\n", string(s))
}
func Info(user *User) {
log.Printf("info level. user:%v\n", user)} func Error(user * user) {// Send SMS messagesdo Something...
log.Printf("error level. user:%v\n", user)
}
Copy the code