Error message here!

Hide Error message here!

忘记密码?

Error message here!

请输入正确邮箱

Hide Error message here!

密码丢失?请输入您的电子邮件地址。您将收到一个重设密码链接。

Error message here!

返回登录

Close

Go language: function is "first class citizen"“

Brother Huanxi 2021-01-21 16:52:10 阅读数:15 评论数:0 点赞数:0 收藏数:0

Video address of this article

Functions are very common in daily work , Whether it's C Language ,C++、Java、Python、JavaScript Are essential .

Go The features of language functions are as follows :
1 func Keyword start .
2 Support multiple return values .
3 Support named return value .
4 Support recursive calls .
5 Supports variable parameters of the same type .
6 Support defer, Let the function return gracefully .

One GO How to make a function become First class citizen Of ?

1 Normal creation . The standard library code is as follows
// $GOROOT/src/fmt/print.go
func newPrinter() *pp {
p := ppFree.Get().(*pp)
p.panicking = false
p.erroring = false
p.wrapErrs = false
p.fmt.init(&p.buf)
return p
}
2 Create... In the function

stay hexdumpWords An anonymous function is defined inside the function ( Assigned to p1)

// $GOROOT/src/runtime/print.go
func hexdumpWords(p, end uintptr, mark func(uintptr) byte) {
p1 := func(x uintptr) {
var buf [2 * sys.PtrSize]byte
for i := len(buf) - 1; i >= 0; i-- {
if x&0xF < 10 {
buf[i] = byte(x&0xF) + '0'
} else {
buf[i] = byte(x&0xF) - 10 + 'a'
}
x >>= 4
}
gwrite(buf[:])
}
... ...
}
3 As a type
// $GOROOT/src/net/http/server.go
type HandlerFunc func(ResponseWriter, *Request)
4 As the reference
$GOROOT/src/time/sleep.go
func AfterFunc(d Duration, f func()) *Timer {
t := &Timer{
r: runtimeTimer{
when: when(d),
f: goFunc,
arg: f,
},
}
startTimer(&t.r)
return t
}
5 As return value
// $GOROOT/src/strings/strings.go
func makeCutsetFunc(cutset string) func(rune) bool {
if len(cutset) == 1 && cutset[0] < utf8.RuneSelf {
return func(r rune) bool {
return r == rune(cutset[0])
}
}
if as, isASCII := makeASCIISet(cutset); isASCII {
return func(r rune) bool {
return r < utf8.RuneSelf && as.contains(byte(r))
}
}
return func(r rune) bool { return IndexRune(cutset, r) >= 0 }
}
Functions other than the examples above , Functions can also be put into arrays 、 section 、map And so on , Can be assigned to like any other type of variable interface{}、 You can also create functions of type channel.

Two Special use of functions

1 Show transformation
var x int = 5
var y int32 = 6
fmt.Println(x + y) 

Run this code , Will report a mistake , Tell you the type doesn't match , You need to type Convert , as follows

var x int = 5
var y int32 = 6
fmt.Println(x + int(y))

Functions are first class citizens , Above are the operations on variables , It can also be applied to functions , That is, functions can also be displayed .

package main
import (
"fmt"
"net/http"
)
func hi(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, “Hi, Gopher!")
}
func main() {
http.ListenAndServe(":8080", http.HandlerFunc(hi))
}

Above is web server Example . When the user enters the port in the browser 8080 when , Will be displayed Hi, Gopher!

Let's see ListenAndServe Source code

// $GOROOT/src/net/http/server.go
func ListenAndServe(addr string, handler Handler) error {
server := &Server{Addr: addr, Handler: handler}
return server.ListenAndServe()
}

http The request is given its second parameter handler Handle , and handler Parameter type is http.Handler Interface

// $GOROOT/src/net/http/server.go
type Handler interface {
ServeHTTP(ResponseWriter, *Request)
}

The interface has only one method ServeHTTP, The archetype is func(http.ResponseWriter, *http.Request), Same as defined above hi The prototype is the same . But you can't directly hi Pass in as a parameter , Otherwise, the report will be wrong ( function hi The interface is not implemented Handler Method , Cannot assign it to Handler Type parameter )
The above code we use http.HandlerFunc(hi) The way , have a look http.HandlerFunc Source code :

// $GOROOT/src/net/http/server.go
type HandlerFunc func(ResponseWriter, *Request)
func (f HandlerFunc) ServeHTTP(w ResponseWriter, r *Request) {
f(w, r)
}

HandlerFunc It's actually a new type based on function definition , Its underlying type is func(ResponseWriter, *Request). This type has a method ServeHTTP, And then it realized Handler Interface .
http.HandlerFunc(greeting) There is no grammatical error in this sentence , Because HandlerFunc The underlying type of is func(ResponseWriter,*Request), And hi The prototypes of the two are the same , This is consistent with the transformation of integer variables we have used . The code is as follows :
type MyInt int
var a int = 666
b:=MyInt(a)

2 Functional programming

 func multiply(x, y int) int {
return x * y
}
func DoWork(x int) func(int) int {
return func(y int) int {
return multiply(x, y)
}
}
func main() {
timesTwo := DoWork(6)
fmt.Println(timesTwo(8))
}
Execute the above code output 48

Accept the original 2 A function of parameters multiply To take a parameter DoWork. adopt DoWork The function structure multiply.
The function here takes advantage of two properties of the function :
1 Define a function in a function body , Return to the outside through the return value .
2 Closure

Closures are anonymous functions defined inside functions , And allow the anonymous function to access the scope of its external function . actually , A closure is a bridge between the inside and outside of a function . above DoWork The internal anonymous function is a closure .

Functional programming
type Do interface {
Work(func(jobName string,content string))
}
type Job struct {
JobName string
Content string
}
func (j Job) Work(fn func(jobName string,content string)) {
fn(j.JobName, j.Content)
}
func WorkDesc(jobName string,content string){
fmt.Println(jobName+""+content)
}
func main() {
job := Job{JobName: " Development work :",Content: " Research and development "}
job.Work(WorkDesc)
}

Run the above code , result :
Development work : Research and development

Delay loading .

Take the Fibonacci series for example , It's also recursive . The code is as follows :

func fab(n int) int {
if n == 1 {
return 1
} else {
return n * fab(n-1)
}
}
func main() {
fmt.Printf("%d\n", fab(10))
}

image

Copyright statement
In this paper,the author:[Brother Huanxi],Reprint please bring the original link, thank you

编程之旅,人生之路,不止于编程,还有诗和远方。
阅代码原理,看框架知识,学企业实践;
赏诗词,读日记,踏人生之路,观世界之行;