Go---函数2

init函数
每一个源文件都可以包含一个init函数, 该函数会在main函数执行前,被Go运行框架
调用,也就是说init 会在main函数前被调用

package main

import (

"fmt"

)

//init函数,通常可以在init函数中完成初始化工作

func init(){

fmt.Println("init......")

}

func main(){

fmt.Println("main......")

}

细节
1)如果一个文件同时包含全局变量定义init 函数main函数,则执行的流程是
全局变量定义--->init函数--->main函数

package main

import (

    "fmt"

)

var age = ttt()

func ttt() int{

    fmt.Println("ttt....")

    return 90

}

//init函数,通常可以在init函数中完成初始化工作

func init(){

    fmt.Println("init......")

}

func main(){

    fmt.Println("main......")

}

 

2) init函 数最主要的作用,就是完成一些初始化的工作。

3)如果main.go和utils.go都含有变量定义,init函数时, 执行的流程

 匿名函数
Go支持匿名函数(没有名字的函数),如果我们某个函数只是希望使用一次,可以考虑使用匿名函数,匿名函数也
可以实现多次调用。
匿名函数使用方式1
在定义匿名函数时就直接调用

//在定义匿名函数时就直接调用,这种方式匿名函数只能调用一次

    res := func (n1 ,n2 int) int {

        return n1-n2

    }(9,6)

    fmt.Println(res)

匿名函数使用方式2
将匿名函数赋给一个变量(函数变量),再通过该变量来调用匿名函数

//将匿名函数func (n1 , n2 int) int赋给a变量

     //则a的数据类型就是函数类型,此时,我们可以通过a完成调用

    a := func (n1 ,n2 int) int {

        return n1+n2

    }

    res2 := a(8,9)

    fmt.Println(res2)

全局匿名函数
如果将匿名函数赋給一个全局变量,那么这个匿名函数,就成为一个全局匿名函数,可以在程
序有效。

var (

    //hs 就是一个全局匿名函数

    hs =func (n1,n2 int) int {

        return n1 * n2

    }

)

 //使用全局匿名函数啊

   res3 := hs(4,4)

   fmt.Println(res3)

闭包
闭包就是一个函数和与其相关的引用环境组合的一个整体(实体)

func AddUpper() func( int ) int {

    var n int =9

    return func ( x int ) int {

        n= n +x

        return n

    }

}

func main(){

f:= AddUpper()

fmt.Println(f(2))

fmt.Println(f(3))

fmt.Println(f(4))

}

说明:

1)  AddUpper是一一个函数,返回的数据类型是fun (int) int
2) 闭包的说明

 返回的是一个匿名函数,但是这个匿名函数引用到函数外的n ,因此这个匿名函数就和n形成一
个整体,构成闭包。

3) 闭包是类,函数是操作,n是字段。函数和它使用到n构成闭包。
4) 当反复的调用f 函数时,因为n是初始化一次,因此每调用一次就进行累计
5) 要搞清楚闭包的关键,就是要分析出返回的函数它使用(引用)到哪些变量,因为函数和它引
用到的变量共同构成闭包。

练习

1) 编写一个函数makesufix(suffix string)可以接收-一个文件后缀名(比如jipg),并返
回一个闭包
2) 调用闭包,可以传入一个文件名,如果该文件名没有指定的后缀(比如.ipg) ,则返
回文件名.jpg,如果已经有jpg后缀,则返回原文件名。
3) 要求使用闭包的方式完成
4)  strings.HasSuffix

func makeSuffix(suffix string) func (string) string {

    return func (name string ) string {

        //如果name 没有指定后缀,则加上,否则就返回原来的名字

        if ! strings.HasSuffix(name,suffix){

            return name + suffix

        }

        return name

    }

}

y := makeSuffix(".jpg")

fmt.Println("deal with after:",y("hhh"))

fmt.Println("deal with after:",y("haha.jpg"))

函数中-defer
在函数中,程序员经常需要创建资源(比如: 数据库连接、文件句柄、锁等),为了在函数执行
完毕后,及时的释放资源,Go的设计者提供defer (延时机制)。

func sum(m1,m2 int) int {

    //当执行到defer时,暂时不执行,会将defer后面的语句压入到独立的栈(defer栈)

    //当函数执行完毕后,再从defer栈, 按照先入后出的方式出栈,执行

    defer fmt.Println("first m1=",m1)//defer  3

    defer fmt.Println("second m2=",m2)//defer 2

    res := m1+m2 //res =

    fmt.Println(" result ==",res)// 1. result =

    return res

}

res := sum(2,2)

fmt.Println(" four ",res) //4

 defer的细节
1) 当go执行到一个defer时, 不会立即执行defer后的语句,而是将defer后的语句压入到一个栈
中暂时称该栈为defer栈, 然后继续执行函数下一个语句。
2) 当函数执行完毕后,在从defer栈中, 依次从栈顶取出语句执行(注:遵守栈先入后出的机制)。

3) 在defer 将语句放入到栈时,也会将相关的值拷贝同时入栈

函数参数的传递方式
值类型参数默认就是值传递,而引用类型参数默认就是引用传递。
  两种传递方式
  1)值传递
  2)引用传递
其实,不管是值传递还是引用传递,传递给函数的都是变量的副本,不同的是,值传递的是值
的拷贝,引用传递的是地址的拷贝,一般来说,地址拷贝效率高,因为数据量小,而值拷贝决
定拷贝的数据大小,数据越大,效率越低。

值类型和引用类型
1) 值类型: 基本数据类型 int系列,float系列, bool, string、数組和结构体struct。
2) 引用类型: 指针、slice切片、map、管道chan、interface 等都是引用类型。

变量作用域
1) 函数内部声明/定义的变量叫局部变量,作用域仅限于函数内部。
2) 函数外部声明/定义的变量叫全局变量,作用域在整个包都有效,如果其首字母为大写,则作用域在整个程序有效。
3) 如果变量是在一个代码块,比如for / if中,那么这个变量的的作用域就在该代码块

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
golang-lru 是一个 Golang 语言实现的 LRU 缓存库,它提供了一个简单易用的 API 用于创建和使用 LRU 缓存。 下面是一个简单的使用示例: ```go package main import ( "fmt" "github.com/hashicorp/golang-lru" ) func main() { // 创建一个 LRU 缓存,容量为 2 cache, _ := lru.New(2) // 添加两个元素到缓存中 cache.Add("key1", "value1") cache.Add("key2", "value2") // 从缓存中获取一个元素 if v, ok := cache.Get("key1"); ok { fmt.Println(v.(string)) } // 添加一个新元素到缓存中,此时缓存容量已满,会自动淘汰最久未使用的元素 "key2" cache.Add("key3", "value3") // 遍历缓存中的所有元素 for _, k := range cache.Keys() { if v, ok := cache.Get(k); ok { fmt.Println(k, v.(string)) } } } ``` 运行上述代码,将会输出: ``` value1 key1 value1 key3 value3 ``` 在这个示例中,我们首先使用 `lru.New()` 函数创建了一个容量为 2 的 LRU 缓存。然后我们添加了两个元素到缓存中,并从缓存中获取了一个元素。接着我们添加了一个新元素,此时缓存已满,会自动淘汰最久未使用的元素 "key2"。最后我们遍历了缓存中的所有元素,输出了它们的键和值。 除了 `Add()` 和 `Get()` 方法外,golang-lru 还提供了 `Remove()` 和 `Contains()` 方法来删除和判断缓存中是否存在某个元素,以及 `Len()` 和 `Clear()` 方法来获取缓存中元素的数量和清空缓存。 golang-lru 还支持并发安全,你可以通过 `NewWithOptions()` 函数创建一个并发安全的 LRU 缓存,具体用法请参考官方文档:https://pkg.go.dev/github.com/hashicorp/golang-lru。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值