zoukankan      html  css  js  c++  java
  • 指针、函数、递归函数、闭包、包

    指针类型 

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

    获取变量量的地址, 用&, 比如: 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路径下

      

     

     

  • 相关阅读:
    解决执行maven项目出现 SLF4J: Failed to load class “org.slf4j.impl.StaticLoggerBinder”. error
    linux yum命令详解
    解决 jenkins 下使用 HTML Publisher 插件后查看 html 报告显示不正常
    Centos6.5上安装sonarqube6.7.6
    Linux下解决高并发socket最大连接数限制,tcp默认1024个连接
    Linux 系统下安装 mysql5.7.25(glibc版)
    高版本sonar安装遇到的坑-sonar 6.7.5
    接口自动化测试框架 :APIAutoTest框架
    Netstat 的 10 个基本用法
    互联网测试开发面试题集锦(二)
  • 原文地址:https://www.cnblogs.com/domestique/p/8169038.html
Copyright © 2011-2022 走看看