<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          Go 學習:那些不一樣的知識點(上)

          共 5926字,需瀏覽 12分鐘

           ·

          2022-09-26 15:41

          c633061d97822f5c22a84531c9921cd0.webp

          在學習 Go 語言的過程中,會涉及到語法、數(shù)據(jù)結(jié)構(gòu)、和一些 Go 特有的東西,其中有不少現(xiàn)在還印象深刻,本文就說說 Go 語言中那些不一樣的地方。

          1、變量和函數(shù)的聲明

                
                package?main

          import?"fmt"

          func?main()?{
          ?var?name?string?//使用?var?關鍵字定義一個名為?name?的字符串類型變量
          ?name?=?"oec2003"?//給變量賦值

          ?age:=18?//使用?:=?來定義變量,會自動進行類型推導,這種方式也是常用的方式

          ?fmt.Println(name,age)
          }

          上面示例是變量的聲明方式,可以看到跟 C# 不同的是,類型是寫在變量名之后的,而在 Go 中的函數(shù)也遵循這個原則:

                
                func?getName(name?string)?string?{
          ?return?"hello,"?+?name
          }
          • 函數(shù)的定義使用 func 關鍵字;
          • 參數(shù)也是類型寫在了參數(shù)名的后面;
          • 函數(shù)的返回值寫在了方法名的后面。

          2、不支持類型的隱式轉(zhuǎn)換

          為了提高代碼的可讀性和避免一些隱藏的錯誤,在 Go 中不支持類型的隱式轉(zhuǎn)換。

          在 C# 中下面的代碼可以正常編譯和運行:

                
                static?void?Main(string[]?args)
          {
          ????int?a?=?18;
          ????long?b?=?a;
          ????Console.WriteLine(b);
          }

          而在 Go 中下面的代碼是會有編譯錯誤的:

                
                func?main()?{
          ?var?a?int16=10
          ?var?b?int32=a
          ?fmt.Println(b)
          }

          int16 和 int32 之間不能隱式轉(zhuǎn)換,只能進行顯示轉(zhuǎn)換,如下:

                
                func?main()?{
          ?var?a?int16?=?10
          ?var?b?int32?=?int32(a)
          ?fmt.Println(b)
          }

          3、運算符

          為了提高生產(chǎn)力,避免在語言中犯錯,Go 有很強的約束性,不支持前置 ++ 和 -- :

                
                func?main()?{
          ?a:=10
          ?a++?//可以支持后置?++?和?--
          ?++a?//不支持前置?++?和?--
          }

          對數(shù)組的比較和 C# 也有區(qū)別,比如在 C# 中比較兩個長度相同、值相同的數(shù)組,返回的是 False :

                
                static?void?Main(string[]?args)
          {
          ????int[]?a?=?new[]?{1,?2,?3};
          ????int[]?b?=?new[]?{1,?2,?3};
          ????Console.WriteLine(a==b);?//?返回?False
          }

          但在 Go 中會有不一樣的結(jié)果:

                
                func?main()?{
          ?a?:=?[...]int{1,?2,?3,?4}
          ?b?:=?[...]int{1,?2,?3,?4}
          ?fmt.Println(a?==?b)?//?長度相同、內(nèi)容相同、值順序相同?返回?ture

          ?b?=?[...]int{1,?2,?3,?5}
          ?fmt.Println(a?==?b)?//?長度不同?返回?false

          ?b?=?[...]int{1,?2,?4,?3}
          ?fmt.Println(a?==?b)?//?長度相同、內(nèi)容相同、值順序不相同?返回?false
          }

          4、map 的值可以是一個函數(shù)

          Go 中的 map 和 C# 中的 Dictionary 有點像,map 的值可以是普通的數(shù)據(jù)類型外,也可以是一個函數(shù):

                
                package?main

          import?(
          ?"fmt"
          )

          func?aa(num?int)?int?{
          ?return?num?*?num
          }
          func?main()?{
          ?m?:=?map[int]func(a?int,?b?int)?int{}
          ?m[1]?=?func(a?int,?b?int)?int?{?return?a?+?b?}
          ?m[2]?=?func(a?int,?b?int)?int?{?return?a?-?b?}
          ?m[3]?=?func(a?int,?b?int)?int?{?return?a?*?b?}
          ?m[4]?=?func(a?int,?b?int)?int?{?return?a?*?b?}

          ?m[1](12,?3)
          ?for?_,?f?:=?range?m?{
          ??fmt.Println(f(12,?3))
          ?}
          }

          //運行結(jié)果如下:
          15
          9
          36
          36

          5、條件判斷

          在 Go 中的條件判斷也有 if 和 switch 兩種。

          if 可以支持在條件的表達式中進行變量賦值:

                
                func?main()?{
          ?m?:=?map[int]string{1:?"oec2003",?2:?"fengwei"}
          ?if?v,?isExist?:=?m[2];?isExist?{
          ??fmt.Println(v)
          ?}?else?{
          ??fmt.Println("不存在")
          ?}
          }
          • if 后的表達式分成了兩段,第一段對變量進行賦值;第二段進行條件的判斷,兩段之間用分號分隔;
          • 第二段的條件判斷必須返回布爾值。

          switch 的使用也有些不一樣的地方:

          • 單個 case 中可以支持多個值,用逗號分隔;
          • 不需要顯示添加 break 來退出 case;
          • switch 后面可以不加任何表達式,就跟 if 類似了。
                
                func?main()?{
          ?switch?os?:=?runtime.GOOS;?os?{
          ?case?"darwin":
          ??fmt.Println("system?is?mac")
          ?case?"linux":
          ??fmt.Println("system?is?linux")
          ?default:
          ??fmt.Println("其他")
          ?}
          }

          //類似?if?else
          name:="oec2003"
          switch{
          ????case?name=="oec2003":
          ????fmt.Println("name?is?oec2003")
          ????default:
          ????fmt.Println("name?is?undefine")
          }

          //case?后面支持多個值
          name?:=?"fengwei"
          switch?name?{
          ????case?"oec2003",?"fengwei":
          ????fmt.Println("都是我的名字")
          ????default:
          ????fmt.Println("不認識")
          }

          6、循環(huán)

          在 Go 語言中,關鍵字非常少,因此,循環(huán)處理只有一個關鍵字 for

                
                //相當于?C#?中的?while
          n?:=?0
          for?n?<?5?{
          ????fmt.Println(n)
          ????n++
          }
          //相當于?C#中的?while(true)
          for{
          ????fmt.Println("這是一個死循環(huán)")
          }
          //?相當于?C#?中的正常的?for
          for?i?:=?0;?i?<?10;?i++?{
          ????fmt.Println(i)
          }
          //?相當于?C#?中的?foreach
          a?:=?[...]int{1,?2,?3,?4}
          for?v?:=?range?a?{
          ????fmt.Println(v)
          }
          • 上面使用一個關鍵字包含了 C# 中所有遍歷的方式;
          • for 后面的表達式不需要寫括號。

          7、特別的 main 函數(shù)

          一個簡單完整的 Go 程序如下所示:

                
                package?main

          import?"fmt"

          func?main()?{
          ?fmt.Println("hello?oec2003!")
          }

          可以看出 Go 的 main 函數(shù)沒有返回值和參數(shù),如果需要在 main 函數(shù)中使用參數(shù),需要引入 os 包:

                
                package?main

          import?(
          ?"fmt"
          ?"os"
          )

          func?main()?{
          ????if?len(os.Args)?>?1?{
          ????????//這里需要注意,第一個參數(shù)下標為?1
          ????????fmt.Println("hello",?os.Args[1])
          ?}
          ????
          ????//遍歷所有的參數(shù)
          ?for?_,?arg?:=?range?os.Args?{
          ??fmt.Println(arg)
          ?}
          }
          • os.Args 是一個字符串的數(shù)組;
          • 使用 range 可以用來遍歷數(shù)組;
          • 在 for中使用 _ 可以忽略第一個參數(shù)。

          8、初始化函數(shù)

          我們知道在 Go 語言中,main 函數(shù)是程序的入口函數(shù),但 main 函數(shù)并不是第一個執(zhí)行的函數(shù),在 main 之前還有 init 函數(shù)會先被執(zhí)行,在 init 函數(shù)中可以做一些初始化的工作:

                
                package?main

          import?(
          ?"fmt"
          )

          func?init()?{
          ?fmt.Println("在這里做初始化工作")
          }
          func?main()?{
          ?fmt.Println("程序開始執(zhí)行")
          }

          9、函數(shù)支持多返回值

          在 C# 中函數(shù)支持多返回值的方式有很多種,比如:返回一個對象、參數(shù)使用 out ,還有就是在 C# 7.0 添加的新功能元組,下面為 C# 中用元組的方式返回多值:

                
                class?Program
          {?
          ????static?void?Main(string[]?args)
          ????{
          ????????var?userInfo?=?GetUserInfo();
          ????????var?name?=?userInfo.name;
          ????????var?age?=?userInfo.age;

          ????????Console.WriteLine(name+age);
          ????}
          ????static?(string?name,?int?age)?GetUserInfo()
          ????{
          ?????return?("oec2003",?18);
          ????}
          }

          Go 語言的函數(shù)返回多值和 C# 的元組的方式比較像:

                
                package?main

          import?(
          ?"fmt"
          )

          func?getUserInfo()?(string,?int)?{
          ?return?"oec2003",?18
          }

          func?main()?{
          ?name,?age?:=?getUserInfo()
          ?fmt.Println(name,?age)
          }

          在接收值時,如果某些值不需要,可以使用 _ 進行忽略:

                
                func?getUserInfo()?(string,?int)?{
          ?return?"oec2003",?18
          }

          func?main()?{
          ?name,_?:=?getUserInfo()
          ?fmt.Println(name)
          }

          10、函數(shù)延遲執(zhí)行

          在 Go 中使用 defer 關鍵字可以讓函數(shù)延遲執(zhí)行,可以用來做釋放資源,釋放鎖等,先看下面的代碼,clear 函數(shù)前面添加了 defer 關鍵字,雖然在 main 函數(shù)第一行,但會最后調(diào)用:

                
                package?main

          import?(
          ?"fmt"
          )

          func?clear()?{
          ?fmt.Println("清理資源")
          }

          func?main()?{
          ?defer?clear()
          ?fmt.Println("程序開始")
          }

          //程序執(zhí)行結(jié)果為
          程序開始
          清理資源

          使用 panic 使程序崩潰,會發(fā)現(xiàn)被 defer 定義的函數(shù)依然會在最后執(zhí)行:

                
                package?main

          import?(
          ?"fmt"
          )

          func?clear()?{
          ?fmt.Println("清理資源")
          }

          func?main()?{
          ?defer?clear()
          ?fmt.Println("程序開始")
          ?panic("程序崩潰啦")
          }

          程序開始
          清理資源
          panic:?程序崩潰啦

          這有點像是在 C# 中使用 try catch ,異常捕獲之后,finally 塊中的代碼還是會被執(zhí)行,我認為 Go 語言的這種處理更加靈活,以組合的方式來達到目的,這也符合 Go 語言的設計哲學。

          相關閱讀:

          Go 學習:從環(huán)境搭建到寫一個 Web 服務

          瀏覽 66
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  亚洲资源在线观看 | 特级西西444www大胆高清图片 | 色婷婷基地伊人 | 九九热这里只有精品12 | 国产操操逼图片 |