Go語言函數詳解

来源:https://www.cnblogs.com/sillyfox/archive/2023/10/27/17791762.html
-Advertisement-
Play Games

函數 (1)函數的定義 函數使用func進行定義 函數是基本的代碼塊,用於執行一個任務 Go語言至少有一個main函數 函數聲明告訴了編譯器函數的名稱,返回類型和參數 //1.無參數無返回值函數的定義 func test1(){ fmt.Println("無參數無返回值函數的定義\n") } //2 ...


函數

(1)函數的定義

  • 函數使用func進行定義
  • 函數是基本的代碼塊,用於執行一個任務
  • Go語言至少有一個main函數
  • 函數聲明告訴了編譯器函數的名稱,返回類型和參數
//1.無參數無返回值函數的定義
func test1(){
    fmt.Println("無參數無返回值函數的定義\n")
}

//2.有參數無返回值函數的定義
func test2(str string){
    fmt.Println("有參無返回值:%s\n",str)
}

//3.多參無返回值
func test3(a,b int) int{
    return a+b
}

//4.多個返回值
func test4(a,b int) (int,int){
    return a,b
}

//函數的調用
fun main()
{
    test1()
    test2("WY")
    test3(1,2)
    test4(5,6)
    
}

(2)函數的可變參數

  • 一個函數的參數類型確定,但個數不確定時可以使用可變參數
  • 定義可變參數時,使用**... **符號
  • 可變參數本質上是保存到了一個數組當中
  • 註意:可變參數要放在參數定義的最後;一個函數的參數列表最多只有一個可變參數
//可變參數函數定義
func add_sum(num...int){
    sum := 0
    for _,i := range num{
        sum += num[i-1]
    }
}

(3)參數傳遞的類型

  • 參數分為兩種類型:

    • 值類型-操作的是數據本身,例如我們常用的:int,string,bool,float64,array
    • 引用類型的數據-操作的是數據的地址:例如slice,map,chan
  • 值傳遞在調用完函數後不會修改原本值傳遞參數的值

//定義一個函數,進行值傳遞實驗
func update(arr2 [4]int){
    fmt.Println("arr2接收到的數據:"arr2)        
    arr2[0] = 100
    fmt.Println("arr2修改後的數據:"arr2)
}

//定義主函數,調用update進行值傳遞觀察
func main(){
    arr := [4]int{1,2,3,4}    //定義一個數組
    fmt.Println(arr)
    //傳遞值
    update(arr)
    fmt.Println("調用後的數據")     //這裡的結果為[1,2,3,4]
}

  • 引用類型數據的參數傳遞在調用完函數後會修改原本值傳遞參數的值
package main

import "fmt"

/*
=====引用傳遞=======
1、定義一個切片
2、通過方法修改切片裡面的數據
3、列印輸出修改後值
*/
func main() {
	arr := []int{1, 2, 3, 4}       //定義一個切片
	fmt.Println("調用修改前的數據", arr)
	updata2(arr)
	fmt.Println("調用修改後的數據", arr)
}
func updata2(arr []int) {
	fmt.Println("arr接受的數據:", arr)
	arr[0] = 100
	fmt.Println("arr修改後的數據:", arr)
}
/*
調用修改前的數據 [1 2 3 4]
arr接受的數據: [1 2 3 4]
arr修改後的數據: [100 2 3 4]
調用修改後的數據 [100 2 3 4]
*/

(4)函數變數的作用域

  • 作用域:變數可以使用的範圍
  • 局部變數:函數內部定義的變數,叫做局部變數,只能在定義該變數的函數內使用
  • 全局變數:函數外部定義的變數,叫做全局變數,可以在任何函數裡面使用
package main

import "fmt"

// 全局變數  所有函數都可以使用
var num int = 30

func main() {
   // 局部變數 temp 只能在定義temp的方法中使用
   temp := 100

   if b := 1; b < 10 {
      temp := 30
      fmt.Println("局部變數b:", b)
      fmt.Println("局部變數temp:", temp)
   }
   fmt.Println(temp)

   // 調用f1,f2方法
   f1()
   f2()
}
func f1() {
   fmt.Println(num)
}
func f2() {
   fmt.Println(num)
}

(5)遞歸函數

  • 遞歸函數的定義:可以自己調用自己的函數
  • 遞歸函數必須要有一個出口,否則會陷入死迴圈
package main

import "fmt"

/*
1、創建一個求和函數 getsum
2、給遞歸函數一個出口
3、創建對象來接收函數
*/
func main() {
	//3、創建對象來接收函數
	sum := getSum(5)

	fmt.Println(sum)
}

//1、創建一個求和函數 getsum
func getSum(n int) int {

	//2、給遞歸函數一個出口
	if n == 1 {
		return 1
	}
	return getSum(n-1) + n
}

(6) defer延遲函數

  • defer函數可以延遲一個函數的執行

在以下代碼塊中,控制台列印的結果是1 2 4 3,因為defer將f(3)延遲到最後執行了

package main

import "fmt"

func main() {

   f("1")
   f("2")
   defer f("3")           //將該函數延遲到最後執行
   f("4")
}
func f(s string) {
   fmt.Println(s)
}

  • 如果使用了多個defer語句,則函數執行到最後時,這些defer語句會按照逆序執行
package main

import "fmt"

func main() {

   f("1")
   f("2")
   defer f("3")
   f("4")
   defer f("5")
   f("6")
   defer f("7")
   f("8")
}
func f(s string) {
   fmt.Println(s)
}
/*
輸出結果:
1
2
4
6
8
7
5
3
*/

(7)func數據類型詳解

  • 在go語言中,函數是複合類型,本質上可以看作是一個特殊的變數

  • func本身就是一個數據類型,func定義的函數之間可以相互賦值

package main

import "fmt"

/*
fun本身就是一個數據類型
1、創建一個函數
2、在mian方法定義相同類型的函數
3、將定義後的函數賦值個另一個函數
*/
func main() {
	//2、在mian方法定義相同類型的函數
	var fg func(int, int)

	//3、將定義後的函數賦值個另一個函數
	fg = ff              //將fg函數定義為ff函數相同的功能
	fg(1, 2)             //最後輸出的結果為 1   2

}

//1、創建一個函數
func ff(a, b int) {
	fmt.Println(a, b)
}



(8)匿名函數

  • 什麼是匿名函數:匿名函數就是沒有名字的函數

匿名函數的創建

//這就是一個匿名函數,但如果直接放在代碼塊中不調用則編譯器會報錯
func() {
    fmt.Println("匿名函數")
}

//帶參匿名函數
func(a,b int){
    fmt.Println("帶參匿名函數")    
}

//帶參且具有返回值函數
func(a,b int) int{
    fmt.Println("帶參和返回值匿名函數")
    return a+b
}

匿名函數多種調用方式

func main(){
    
    //方式1:用一個變數調用匿名函數
    f3 := func(){
        fmt.Println("匿名函數的調用方式1")
    }
    f3() //調用匿名函數
    
    //方式2:創建匿名函數後直接調用func(),在{}後直接添加()進行調用
    func(){
        fmt.Println("匿名函數調用方式2")
    }()
    
    //帶參匿名函數的調用
    func(a,b int){
        fmt.Println("帶參匿名函數調用")
    }(1,2)    
    
    //帶參和返回值匿名函數調用
    f5 := func(a,b int) int{
        fmt.Println("帶參和返回值匿名函數")
        return a+b
    }(1,2)    
    fmt.Println(f5)     //列印調用結果
    
}

(9)高階函數和回調函數

  • 回調函數:將一個函數作為另一個函數的參數

  • 若將fun1函數作為fun2函數的參數,則fun2叫做高階函數,fun1稱為回調函數

package main

import "fmt"

//1、創建一個高階函數oper,傳如一個函數類型的參數且有返回值
func oper(a, b int, fun func(int, int) int) int {
	r2 := fun(a, b)
	return r2
}

//2.創建其他方法的函數
func add(a, b int) int {
	return a + b
}

//創建其他方法的函數
func sub(a, b int) int {
	return a - b
}

func main() {
	r1 := add(1, 2)
	fmt.Println(r1)

	//3、調用高階函數時,傳入其他方法的函數
	r3 := oper(3, 4, add)
	fmt.Println(r3)
	r4 := oper(8, 4, sub)
	fmt.Println(r4)
}





(10)閉包

  • 一個外層函數中,有內層函數,該內層函數中,會操作外層函數的局部變數並且該外層函數的返回值就是這個內層函數
  • 這個內層函數和外層函數的局部變數,統稱為閉包結構。
  • 局部變數的生命周期就會發生改變,正常的局部變數會隨著函數的調用而創建,隨著函數的結束而銷毀但是閉包結構中的外層函數的局部變數並不會隨著外層函數的結束而銷毀,因為內層函數還在繼續使用
package main

import "fmt"

// 定義一個閉包函數。func() int是局部變數和返回值fun的類型
func increment() func() int {

	//局部變數
	i := 0
	//定義一個匿名函數 給變數自增並返回
	fun := func() int {
		//內層函數,沒有執行
		i++
		return i
	}
	return fun
}

func main() {
	//定義一個變數 接受返回值(函數)
	r1 := increment()      //創建函數
	fmt.Println(r1)       //這裡列印的是地址,因為r1還沒有執行

	v1 := r1()
	fmt.Println(v1)
	//不斷調用自增+1
	v2 := r1()
	fmt.Println(v2)
	//不斷調用自增+1
	fmt.Println(r1())
	fmt.Println(r1())
	fmt.Println(r1())
	fmt.Println(r1())
	fmt.Println("====================")
	//	==========================================================
	r2 := increment()      //創建函數,i也會清零
	v3 := r2()
	fmt.Println(v3)
	fmt.Println(r2())
	fmt.Println(r2())
	fmt.Println(r2())
	fmt.Println(r1())     //這裡調用的是r1,因此i值還是原來r1的i值,這裡自增後為7
	fmt.Println(r2())
}


/*
輸出結果:
0xd5ea00
1
2
3
4
5
6
====================
1
2
3
4
7
5

*/


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 非功能性需求是什麼呢?保障系統持續健康運轉的輔助需求。依然以電商系統的優惠券為例,在促銷活動期間發放大量優惠券,如何防止用戶集中領券時系統不崩盤呢?活動結束後,如何收縮伺服器,節省伺服器資源呢? 非功能性需求是面向運維的,重要但是不太緊迫,有時候可以沒有操作界面,由架構師提出解決方案,再推動各個業務... ...
  • 單詞 "多態" 意味著 "多種形式",在編程中,它指的是具有相同名稱的方法/函數/操作符,可以在許多不同的對象或類上執行。 函數多態性 一個示例是 Python 中的 len() 函數,它可以用於不同的對象。 字元串 對於字元串,len() 返回字元的數量: 示例 x = "Hello World! ...
  • PDF(Portable Document Format)是一種常用的文檔格式,具有跨平臺相容性、保真性、安全性和交互性等特點。我們日常生活工作中的合同、報告、論文等通常都採用PDF格式,以確保文檔在不同的操作系統(例如 Windows、Mac、Linux)和設備上被查看時都能保持外觀的一致性。 P ...
  • 本章節主要講的是如何配置熱載入,會碰到什麼問題,要怎麼處理。`wmproxy`是由`Rust`編寫,已實現`http/https`代理,`socks5`代理, 反向代理,靜態文件伺服器,內網穿透,配置熱更新等, ...
  • 字元串中的BKDRHash哈希函數 在電腦科學中,哈希函數是一種將任意長度的輸入(也稱為“消息”)通過散列演算法轉換成固定長度的輸出,該輸出就是哈希值。哈希函數的一個重要特性是,對於相同的輸入,無論何時執行哈希函數,它都應該產生相同的輸出。然而,對於不同的輸入,即使它們只有微小的差別,哈希函數也應該 ...
  • 本文分享自華為雲社區《深入理解Java中的Reader類:一步步剖析》,作者:bug菌。 前言 在Java開發過程中,我們經常需要讀取文件中的數據,而數據的讀取需要一個合適的類進行處理。Java的IO包提供了許多類用於數據的讀取和寫入,其中Reader便是其中之一。本文將對Java中的Reader進 ...
  • 這是做什麼用的 框架用途 在採集大量新聞網站時,不可避免的遇到動態載入的網站,這給配模版的人增加了很大難度。本來配靜態網站只需要兩個技能點:xpath和正則,如果是動態網站的還得抓包,遇到加密的還得js逆向。 所以就需要用瀏覽器渲染這些動態網站,來減少了配模板的工作難度和技能要求。動態載入的網站在新 ...
  • Hutool它是一個Java工具集類庫,包含了很多靜態方法的封裝:流處理、時間日期處理、正則處理、加解密處理、文件處理、集合處理等,可以說是項目中幾乎所有XxxxUtil的替代品,它可以使你更多的關註代碼邏輯,優雅的寫出高效代碼,避免“複製粘貼,改改再戰”。 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...