指针、函数、递归函数、闭包、包

指针类型 

普通类型,变量量存的就是值,也叫值类型。指针类型存的是地址 

获取变量量的地址, 用&, 比如: var a int, 获取a的地址:&a

指针类型,变量量存的是一个地址,这个地址存的才是值

获取指针类型所指向的值,使用:*, 比如:var *p int, 使用*p获取p指向的值

package main

import(
    "fmt"
)

func test1() {
    var a int
    a = 10
    fmt.Println(a)

    var b *int
    fmt.Printf("%p
", &b)   //指针这个变量的内存地址
    fmt.Printf("%p
", b)    //指针的内存地址
    fmt.Printf("%p
", a)    //常量
    fmt.Printf("%p
", &a)   //常量的内存地址

    b = &a                   //将常量的内存地址指向指针
    fmt.Printf("%d
", *b)

    *b = 100                 //改变指针内存对应的值
    fmt.Printf("a=%d
", a)
}

func modify(a *int) {
    *a = 100
}

func test2() {
    var b int = 1
    var p *int 
    p =  &b
    modify(p)
    fmt.Println(b)
}

func test3() {

    //p 默认初始化nil
    //指针的初始化
    var p *int
    var b int
    p = &b
    *p = 200 //b = 200
    fmt.Printf("%p %p %p
", p, &b, &p)
    
    //指针的初始化
    p = new(int)
    *p = 1000
    fmt.Printf("%d
", *p)
    fmt.Printf("%p %p %p
", p, &b, &p)
    //指针类型的变量初始化:1. 使用其他变量地址给它赋值。 2. 使用new分配。
}

func test4(){
    var p *string    
    //1. 第一种方式  使用new分配。
    p = new(string)
    *p = "abc"
    fmt.Println(*p)

    //2. 第二种方式  使用其他变量地址给它赋值。
    var str string = "hello word"
    p = &str
    fmt.Println(*p)
}

func test5(){
    //make和new的区别
    var a []int
    a  = make([]int, 10)
    a[0] = 100
    fmt.Println(a)

    var p *[]int   
    p = new([]int) //给指针分配内存地址 
    (*p) = make([]int, 10)  //初始化切片
    (*p)[0] = 100
    fmt.Println(p)

    p = &a 
    (*p)[0] = 1000
    fmt.Println(a)
}

func modify_arr(a []int) {
    fmt.Printf("modify:%p
", a)
    a[0] = 100   //改变数据的的值
}

func test6() {
    var a[6]int 
    fmt.Printf("test6:%p
", &a)
    modify_arr(a[:])  //切片是引用类型数据
    fmt.Println(a)
}

func main() {
    //test1()
    //var a int
    //test2(&a)
    //fmt.Println(a)
    //test3()
    //test4()
    //test5()
    test6()
}
View Code

内置函数

1、close:主要 用来关闭channel 

2、len: 用来求 长度, 比如string、array、slice、map、channel 

3、new: 用来分配内存,主要用来分配值类型, 比如int、struct、string。返回的是指针 

4、make: 用来分配内存,主要用来分配引 用类型, 比如chan、map、slice 

5、append: 用来追加元素到数组、slice中 

6、panic和recover: 用来做错误处理理 

7、new和make的区别

函数

1、声明语法:func 函数名 (参数列列表) [(返回值列列表)] {}

func add() {

}

func add(a int, b int) {

 }

func add(a int, b int) int { 

}

func add(a int, b int) (int, int) {

 }

func add(a, b int) (int, int) {

 }

2、golang函数特点: 

不支持重载, 一个包不能有两个名字一样的函数。 

函数是一等公民,函数也是一种类型, 一个函数可以赋值给变量 

匿名函数 

多返回值

package main

import "fmt"

func add(a, b int) int {
  return a + b
}

func main() {
  //函数是一等公民,也可以和变量量一样进行行赋值
  c := add
  fmt.Printf("%p %T %p %T
", c, add, c,add)
  sum := c(10, 20)
  fmt.Println(sum)
  sum = add(10, 20)
  fmt.Println(sum)

}
package main
import "fmt"
type add_func func(int, int) int //自己定义数据类型
func add(a, b
int) int {   return a + b } func operator(op add_func, a int, b int) int {   //使用传进来的函数,进行操作,op函数,类型为add_func
  return op(a, b) } func main() {   c := add   fmt.Println(c)   sum := operator(c, 100, 200)   fmt.Println(sum) }

3、函数参数传递 方式: 

1). 值传递 

2). 引用传递

注意1: 无论是值传递,还是引用传递,传递给函数的都是变量量的副本,不过,值传递是值的拷贝。引用传递是地址的拷贝, 一般来说,地址拷贝更为高效。 而值拷贝取决于拷贝的对象大小,对象越大,则性能越低。

3).函数参数传递方式:

注意2mapslicechan、指针、interface默认以引用的方式传递

4、命名返回值的名字:

func add(a, b int) (c int) {
    c = a + b
    return

}

func calc(a, b int) (sum int, avg int) {
    sum = a + b
    avg = (a +b)/2
    return

}

5、_标识符, 用来忽略略返回值:

func calc(a, b int) (sum int, avg int) {
    sum = a + b
    avg = (a +b)/2
    return

}

func main() {
    sum, _ := calc(100, 200)
}

6、可变参数:

func add(arg…int) int {    
        //0或多个参数
}

func add(a int, arg…int) int {
        //1个或多个参数
}    


func add(a int, b int, arg…int) int {    
        //2个或多个参数
}

注意:其中arg 一个slice,我们可以通过arg[index]依次访问所有参数通过len(arg)来判断传递参数的个数。

7、defer 用途:

  1)当函数返回时,执行defer语句。因此,可以用来做资源清理

  2)多个defer语句,按先进后出的方式执行

  3) defer语句中的变量,在defer声明时就决定了。  

  defer 行为特征:

func a() {
    i := 0
    defer fmt.Println(i)
    i++
    return
}
func f() {
  for i := 0; i < 5; i++ {
    defer fmt.Printf(“%d “, i)  
  }
}

  defer 用途:

  1. 关闭文件句柄 
func read() {
    file := open(filename)
    defer file.Close()
    // 文件操作
}

  2.锁资源释放

func read() {
    mc.Lock()
    defer mc.Unlock()
    //其他操作
}

  3.数据库连接释放

func read() {
    conn := openDatabase()
    defer conn.Close()
    //其他操作
}

递归函数

  一个函数调用自己,就叫做递归。

package main

import (

    "fmt"
)

func calc(n int) int {
    if n == 1 {
        return 1
    }
    return calc(n-1) * n
}


func main() {
    n := calc(5)
    fmt.Println(n)
}

  递归的设计原则

  1 一个大的问题能够分解成相似的小问题

  2)定义好出 口条件

 闭包

  1. 闭包:一个函数和与其相关的引用环境组合而成的实体。 
func Adder() func(int)int {
    var x int  //在闭包中相当于全局变量
f :
= func(i int)int { x = x + i return x } return f } func testClosure() { f1 := Adder()//函数的调用,不是函数的赋值
fmt.Println(f1(
10))//10
fmt.Println(f1(
20))//30
fmt.Println(f1(
30))//60 }

 应用举例

package main

import (
    "fmt"
    "strings"
)

func makeSuffixFunc(suffix string) func(string) string { 
    return func(name string) string {
        if !strings.HasSuffix(name, suffix) {
            return name + suffix
        }
        return name
    }
}

func main() {
    func1 := makeSuffixFunc(".bmp")
    func2 := makeSuffixFunc(".jpg")
    fmt.Println(func1("test"))
    fmt.Println(func2("test"))
}

 

1、golang中的包

  a.golang 目前有150个标准的包,覆盖了几乎所有的基础库

  b.golang.org有所有包的文档,没事都翻翻

线程同步

a.import(“sync”)

b.互斥锁, var mu sync.Mutex

c.读写锁, var mu sync.RWMutex

2、go get安装第三方包

  go get github.com/gorilla/websocket,包会装在GOPATH路径下

  

 

 

原文地址:https://www.cnblogs.com/domestique/p/8169038.html