亚洲免费在线-亚洲免费在线播放-亚洲免费在线观看-亚洲免费在线观看视频-亚洲免费在线看-亚洲免费在线视频

對比學習:Golang VS Python3

系統 1802 0

Golang和Python都是目前在各自領域最流行的開發語言之一。

Golang其高效而又友好的語法,贏得了很多后端開發人員的青睞,最適用于高并發網絡編程的語言之一。

Python不用說,TIOBE排行榜的前十常駐居民,現在已經穩定在前五了。在機器學習、AI、數據分析領域成為必學語言。

兩門編程語言在語法上都有各自的特點,而且都 易學易用

本文對比這兩門語言目的不是爭誰優誰略,只是為了對比學習,適合掌握Python想學Go或者掌握Go想學Python的同學們參考。

Go和Python,一個是靜態語言一個是動態語言,從各個方面來看,都有根本性的差異,所以,文中很多內容不進行深入的比較了,我們只從程序員最直觀的語法面做對比。

為了便于閱讀,文中涉及代碼都采用盡量簡單的語句呈現

字符編碼

Python

Python中默認的編碼格式是 ASCII 格式,程序文件中如果包含中文字符(包括注釋部分)需要在文件開頭加上 # -*- coding: UTF-8 -*- 或者 #coding=utf-8 就行了

Golang

原生支持Unicode

保留字(關鍵字)

Python

30個關鍵字

          
            and    exec    not
assert    finally    or
break    for    pass
class    from    print
continue global    raise
def    if    return
del    import    try
elif    in    while
else    is    with
except    lambda    yield
          
        

Golang

25個關鍵字

          
            break    default    func    interface    select
case    defer    go    map    struct
chan    else    goto    package    switch
const    fallthrough    if    range    type
continue    for    import    return    var
          
        

注釋

Python

          
            # 單行注釋

'''
多行注釋
多行注釋
'''

"""
多行注釋
多行注釋
"""

          
        

Golang

          
            //單行注釋

/*
多行注釋
多行注釋
*/
          
        

變量賦值

Python

Python是動態語言,所以在定義變量的時候不需要申明類型,直接使用即可。
Python會根據值判斷類型。

          
            name = "Zeta" # 字符串變量
age = 38 # 整數
income = 1.23 # 浮點數
          
        

多變量賦值

          
            a,b = 1,2 # a=1; b=2
c = d = 3 # c=3; d=3
          
        

Golang

Go是靜態語言,是強類型的,但是Go語言也允許在賦值變量時確定類型。

因此Go有多種申明變量的方式

          
            // 1. 完整的申明并賦值
var a int
a = 1

// 2. 聲明變量類型同時賦值
var a int = 1

// 3. 不聲明類型,賦值時確定
var a = 1

// 4. 不用 var 關鍵字申明變量并賦值后確定類型
a := 1
          
        

注意,Go中的new關鍵字并不是聲明變量,而是返回該類型的指針

          
            a := new(int) //這時候a是一個*int指針變量
          
        

標準數據類型

Python 的標準數據類型有:

  • Boolean(布爾值)
  • Number(數字)
  • String(字符串)
  • List(列表)
  • Tuple(元組)
  • Set(集合)
  • Dictionary(字典)

Golang

  • boolean(布爾值)
  • numeric(數字)
  • string(字符串)
  • 數組(數組)
  • slice(切片:不定長數組)
  • map(字典)
  • struct(結構體)
  • pointer(指針)
  • function(函數)
  • interface(接口)
  • channel(通道)

總結

Python中的 List列表 對應Go語言中的 Slice切片

Python中的 Dictionary字典 對應Go語言中的 map

有一些值得注意的地方:

  • Go是支持函數編程的語言,所以在Go語言中函數是一個類型
  • Go語言不是面向對象的語言,沒有定義類的關鍵字Class,要實現OOP風格編程,是通過struct、interface類型實現的
  • Python中的元組和集合在Go中都沒有
  • channel是Go里獨有的類型,多線程之間的通信就靠它

數據類型轉換

Python

Python類型轉換非常簡單,用類型名作為函數名即可。

          
            int(n)            # 將數字n轉換為一個整數
float(n)          # 將數字n轉換到一個浮點數
str(o)            # 將對象 obj 轉換為字符串
tuple(s)          # 將序列 s 轉換為一個元組
list(s)           # 將序列 s 轉換為一個列表
set(s)            # 將序列 s 轉換為一個集合
          
        

Golang

Go語言的基礎類型轉換和Python差不多,也是用類型名作為函數名

          
            i := 1024
f := float32(i)
i = float32(f)
          
        

另外,Python中可以直接轉換數字字符串和數字:

          
            s = "123"
i = 456
print(int(s), str(i))
          
        

但是Go是不可以的。

Go語言的字符串處理很不同, string() 只能用于 []byte 類型轉換成字符串,其他基礎類型的轉換需要用 strconv 包,另外,其他類型轉換成為 string 類型除了用 strconv 包,還可以用 fmt.Sprintf 函數:

          
            package main

import (
    "fmt"
    "strconv"
)

func main() {
    s := "123"
    i, _ := strconv.Atoi(s)
    println(i)

    s2 := fmt.Sprintf("%d", 456)
    println(s2)
}
          
        

Go中的interface類型是不能直接轉換成其他類型的,需要使用到 斷言

          
            package main

func main() {
var itf interface{} = 1
i, ok := itf.(string)
println("值:", i, "; 斷言結果", ok)

j, ok := itf.(int)
println("值:", j, "; 斷言結果", ok)
}
          
        

輸出為:

          
            值:  ; 斷言結果 false
值: 1 ; 斷言結果 true
          
        

條件語句

Python

Python傳統的判斷語句如下

          
            if name == 'zeta':          # 判斷變量是否為 zeta 
    print('Welcome boss')   # 并輸出歡迎信息
else:
    print('Hi, ' + name)  
          
        

Python不支持三元表達式,但是可以用一種類似的替代辦法

          
            title = "boss"
name = "zeta" if title == "boss" else "chow"
print(name)
          
        

邏輯與用 and ,邏輯或用 or

Golang

Go的 if 的語法類似Java,但是表達式不需要使用 ()

          
            if a > b{
    println("a > b")
} else {
    println("a <= b")
}
          
        

Go同樣沒有三元表達式,并且也沒有什么替代方法。

另外,Go允許在 if 的表達式里定義變量,定義并賦值的表達式與判斷的表達式用 ; 隔開,常見的情況是獲取函數返回error,然后判斷error是否為空:

          
            if err := foo(); err != nil {
    println("發生一些錯誤")
} 
          
        

與Python不同,邏輯與用 && , 邏輯或用 ||

循環語句

Python

Python中有 while for 兩種循環,都可以使用 break 跳出循環和 continue 立即進入下一輪循環,另外,Python的循環語句還可以用 else 執行循環全部完畢后的代碼, break 跳出后不會執行 else 的代碼

while 條件循環,

          
            count = 0
while (count < 9):
    print('The count is:', count)
    count = count + 1
    if count == 5:
        break   # 可以比較以下break和不break的區別
        pass
else:
    print('loop over')
          
        

for 遍歷循環,循環遍歷所有序列對象的子項

          
            names = ['zeta', 'chow',  'world']
for n in names:
    print('Hello, ' + n)
    if n == 'world':
        break
        pass
else:
    print('Good night!')
          
        

for 循環中也可以用 else ,(注釋掉代碼中的 break 試試看。)

Golang

Go語言只有一個循環語句 for ,但是根據不同的表達式, for 有不同的表現

          
            for 前置表達式; 條件表達式; 后置表達式 {
    //...
}
          
        

前置表達式 在每輪循環前運行,可以用于聲明變量或調用函數返回;
條件表達式 滿足該表達式則執行下一輪循環,否則退出循環;
后置表達式 在循環完成后執行

經典的用法:

          
            for i := 0; i < 10; i++ {
    println(i)
}
          
        

我們可以忽略掉前置和后置表達式

          
            sum := 1
for sum < 10 {
    sum += sum
}
          
        

設置可以忽略掉全部表達式,也就是無限循環

          
            for {
    print(".")
}
          
        

Go的 for 循環同樣可以使用 break 退出循環和 continue 立即進行下一輪循環。

for 除了配合表達式循環,同樣也可以用于遍歷循環,需要用到 range 關鍵字

          
            names := []string{"zeta", "chow", "world"}
for i, n := range names {
    println(i,"Hello, " + n)
}
          
        

函數

Python

def 關鍵字定義函數,并且在Python中,作為腳本語言,調用函數必須在定義函數之后。

          
            def foo(name):
    print("hello, "+name)
    pass

foo("zeta")
          
        

默認參數 Python定義函數參數時,可以設置默認值,調用時如果沒有傳遞該參數,函數內將使用默認值,默認值參數必須放在無默認值參數后面。

          
            def foo(name="zeta"):
    print("hello, "+name)
    pass

foo()
          
        

關鍵字參數 一般函數傳遞參數時,必須按照參數定于的順序傳遞,但是Python中,允許使用關鍵字參數,這樣通過指定參數明,可以不按照函數定義參數的順序傳遞參數。

          
            def foo(age, name="zeta"):
    print("hello, "+name+"; age="+str(age))
    pass

foo(name="chow", age=18)
          
        

不定長參數 ,Python支持不定長參數,用 * 定義參數名,調用時多個參數將作為一個元祖傳遞到函數內

          
            def foo(*names):
    for n in names:
        print("hello, "+n)
    pass

foo("zeta", "chow", "world")
          
        

return 返回函數結果。

Golang

Go用 func 定義函數,沒有默認值參數、沒有關鍵字參數,但是有很多其他特征。

          
            func main() {
    println(foo(18, "zeta"))
}

func foo(age int, name string) (r string) {
    r = fmt.Sprintf("myname is %s , age %d", name, age)
    return 
}
          
        

函數的定義和調用沒有順序的限制。

Go的函數不僅可以定義函數返回值類型,還可以申明返回值變量,當定義了返回值變量時,函數內的 return 語句可以不需要帶返回值,函數會默認使用返回值變量返回。

可變參數

使用 …類型 定義可變參數,函數內獲得的參數實際是該 類型 slice 對象

          
            func main() {
    println(foo(18, “zeta”, “chow”, “world”))
}

func foo(age int, names …string) (r string) {
    for _, n := range names {
        r += fmt.Sprintf(“myname is %s , age %d \n”, n, age)
    }

    return
}
          
        

defer句

defer 語句后面指定一個函數,該函數會延遲到本函數return后再執行。

defer語句在Go語言中非常有用,詳細可以查閱本專欄的另一篇文章《 Golang研學:如何掌握并用好defer(延遲執行)

          
            func foo() {
    defer fmt.Println("defer run")
    fmt.Println("Hello world")
    return
}
          
        

運行結果:

          
            Hello world
defer run
          
        

另外,在Go語言中 函數也是類型 ,可以作為參數傳遞給別的函數

          
            func main() {
    n := foo(func(i int, j int) int {
        return i + j
    })
    println(n)
}

func foo(af func(int, int) int) int {
    return af(1, 2)
}
          
        

上面這個例子直接在參數定義時使用函數類型,看上去有點混亂

再看來看一個清晰并完整的例子,說明全在注釋里。

          
            package main

type math func(int, int) int //定義一個函數類型,兩個int參數,一個int返回值

//定義一個函數add,這個函數兩個int參數一個int返回值,與math類型相符
func add(i int, j int) int {
    return i + j
}

//再定義一個multiply,這個函數同樣符合math類型
func multiply(i, j int) int {
    return i * j
}

//foo函數,需要一個math類型的參數,用math類型的函數計算第2和第3個參數數字,并返回計算結果
//稍后在main中我們將add函數和multiply分別作為參數傳遞給它
func foo(m math, n1, n2 int) int {
    return m(1, 2)
}

func main() {
    //傳遞add函數和兩個數字,計算相加結果
    n := foo(add, 1, 2)
    println(n)

    //傳遞multply和兩個數字,計算相乘結果
    n = foo(multiply, 1, 2)
    println(n)
}
          
        

結果

          
            3
2
          
        

模塊

Python

  • 模塊是一個.py文件
  • 模塊在第一次被導入時執行
  • 一個下劃線定義保護級變量和函數,兩個下劃線定義私有變量和函數
  • 導入模塊習慣性在腳本頂部,但是不強制

Golang

  • 與文件和文件名無關,每一個文件第一行用package定義包名,相同包名為一個包
  • 包中的變量第一次引用時初始化,如果包中包含init函數,也會在第一次引用時執行(變量初始化后)
  • 保重首寫字母大寫的函數和變量為共有,小寫字母為私有,Golang不是面向對象的,所以不存在保護級。
  • 導入模塊必須寫在package之后,其他代碼之前。

導入包

Python

在Python中,使用 import 導入模塊。

          
            #!/usr/bin/python
# -*- coding: UTF-8 -*-
 
# 導入模塊
import support
 
support.print_func(“Runoob”)
          
        

還可以使用 from import 導入模塊指定部分

          
            from modname import name1[, name2[, ... nameN]]
          
        

為導入的包設置別名用 as 關鍵字

          
            import datetime as dt
          
        

Golang

也是使用 import 導入包,導入包指定的是包的路徑,包名默認為路徑中的最后部分

          
            import "net/url" //導入url包
          
        

多個包可以用 () 組合導入

          
            import (
    "fmt"
    "net/url"
)
          
        

為導入的包設置別名, 直接在導入包時,直接在報名前面添加別名,用空格隔開

          
            import (
    f "fmt"
  u "net/url"
)
          
        

錯誤和異常

Python

Python中用經典的 try/except 捕獲異常

          
            try:
<語句>        #運行別的代碼
except <異常名稱>:
<語句>        #
except <異常名稱>,<數據>:
<語句>        #如果引發了指定名稱的異常,獲得附加的數據
          
        

還提供了 else finally

如果沒發生異常的執行 else 語句塊, finally 塊的代碼無論是否捕獲異常都會執行

Python內建了很全面的異常類型名稱,同時能自定義異常類型

Golang

Golang里沒有用經典的 try/except 捕獲異常。

Golang提供兩種錯誤處理方式

  1. 函數返回 error 類型對象判斷錯誤
  2. panic 異常

一般情況下在Go里只使用 error 類型判斷錯誤,Go官方希望開發者能夠很清楚的掌控所有的異常,在每一個可能出現異常的地方都返回或判斷 error 是否存在。

error 是一個內置的接口類型

          
            type error interface {
    Error() string
}
          
        

通常,使用 error 異常處理類似這樣:

          
            package main

import "fmt"

func foo(i int, j int) (r int, err error) {
    if j == 0 {
        err = fmt.Errorf("參數2不能為 %d", j) //給err變量賦值一個error對象
        return //返回r和err,因為定義了返回值變量名,所以不需要在這里寫返回變量
    }

    return i / j, err //如果沒有賦值error給err變量,err是nil
}

func main() {
    //傳遞add函數和兩個數字,計算相加結果
    n, err := foo(100, 0)
    if err != nil { //判斷返回的err變量是否為nil,如果不是,說明函數調用出錯,打印錯誤內容
        println(err.Error())
    } else {
        println(n)
    }
}
          
        

panic 可以手工調用,但是Golang官方建議盡量不要使用 panic ,每一個異常都應該用error對象捕獲。

Go語言在一些情況下會觸發內建的 panic ,例如 0 除、數組越界等,修改一下上面的例子,我們讓函數引起0除 panic

          
            package main

func foo(i int, j int) (r int) {
    return i / j
}

func main() {
    //傳遞add函數和兩個數字,計算相加結果
    n := foo(100, 0)
    println(n)
}
          
        

運行后會出現

          
            panic: runtime error: integer divide by zero
goroutine 1 [running]:
main.foo(...)
        /lang.go:4
main.main()
        /lang.go:9 +0x12
exit status 2
          
        

手工 panic 可以這樣:

          
            func foo(i int, j int) (r int) {
    if j == 0 {
        panic("panic說明: j為0")
    }
    return i / j
}
          
        

運行后,可以看到,錯誤消息的第一句:

          
            panic: panic說明: j為0
          
        

面向對象

Python

Python完全支持面向對象的。

Golang

盡管Go語言允許面向對象的風格編程,但是本身并不是面向對象的

官方FAQ原文

Is Go an object-oriented language?

Yes and no. Although Go has types and methods and allows an object-oriented style of programming, there is no type hierarchy. The concept of “interface” in Go provides a different approach that we believe is easy to use and in some ways more general. There are also ways to embed types in other types to provide something analogous—but not identical—to subclassing. Moreover, methods in Go are more general than in C++ or Java: they can be defined for any sort of data, even built-in types such as plain, “unboxed” integers. They are not restricted to structs (classes).

多線程

Python

  1. 使用 thread 模塊中的 start_new_thread() 函數
  2. 使用 threading 模塊創建線程

Golang

用關鍵 go 創建協程 goroutine

go 關鍵字后指定函數,將會開啟一個協程運行該函數。

          
            package main

import (
    "fmt"
    "time"
)

func foo() {
    for i := 0; i < 5; i++ {
        fmt.Println("loop in foo:", i)
        time.Sleep(1 * time.Second)
    }
}

func main() {
    go foo()

    for i := 0; i < 5; i++ {
        fmt.Println("loop in main:", i)
        time.Sleep(1 * time.Second)
    }
    time.Sleep(6 * time.Second)
}
          
        

Go語言中,協程之間的通信是通過 channel 實現的:

          
            package main

import (
    "fmt"
    "time"
)

//接受一個chan類型的參數c
func foo(c chan int) { 
    time.Sleep(1 * time.Second) //等待1秒
    c <- 1024                   //向c中寫入數字
}

func main() {
    c := make(chan int) //創建chan變量c
    go foo(c)           //在子寫成中運行函數foo,并傳遞變量c
    fmt.Println("wait chan 'c' for 1 second")
    fmt.Println(<-c) //取出chan 'c'的值(取值時,如果c中無值,主縣城會阻塞等待)
}
          
        

總結

Python和Go分別在動態語言和靜態語言中都是最易學易用的編程語言之一。

它們并不存在取代關系,而是各自在其領域發揮自己的作用。

Python的語法簡單直觀,除了程序員愛不釋手外也非常適合于其他領域從業者使用。

Go兼具語法簡單和運行高效的有點,在多線程處理方面很優秀,非常適合已經掌握一定編程基礎和一門主流語言的同學學習,不過,Go是不支持面向對象的,對于大多數支持面向對象語言的使用者在學習Go語言的時候,需要謹記并且轉換編程思路。

后記

文中還有許多應該涉及的知識卻沒有能夠詳細說明,它是不完整的,甚至難免會有一些失誤。

如果,您覺得本文對您有所幫助,希望能夠得到您的點贊支持,如果文中有錯誤的地方,也希望不吝賜教,通過評論或者公眾號和大家一起交流學習。


更多文章、技術交流、商務合作、聯系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯系: 360901061

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對您有幫助就好】

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長會非常 感謝您的哦!!!

發表我的評論
最新評論 總共0條評論
主站蜘蛛池模板: 久久综合精品国产一区二区三区无 | 亚洲一区二区三区高清不卡 | 久久国产精品免费看 | 精品999久久久久久中文字幕 | 羞羞视频网站在线观看 | 国产精品亚洲综合一区在线观看 | 日本高清不卡视频 | 亚洲五月色 | 国产高清不卡一区二区三区 | 国产精品播放 | 欧美日韩中文在线视频 | 亚洲黄色在线视频 | 成人精品免费网站 | 四虎激情 | 久久久久久久久免费视频 | 骚碰97| www深夜视频在线观看高清 | 欧美日韩在线精品成人综合网 | 天天干在线免费视频 | 亚洲精品乱码久久久久久蜜桃 | 99r在线 | 天天干视频网站 | 午夜久久免费视频 | 一及 片日本 | 午夜一级大片 | 亚洲欧美一二三区 | 国产成人精品久久一区二区小说 | 99久久精品免费观看国产 | 亚洲欧美人成综合在线最新 | 久久五月天婷婷 | 奇米影视四色狠狠888俺去啦 | 亚洲综合图片人成综合网 | 7777精品伊人久久久大香线蕉 | 青青青激情视频在线最新 | 国产日韩久久久精品影院首页 | 国产亚洲精品欧美一区 | 97干色| 久久精品视频免费在线观看 | 一级国产20岁美女毛片 | 四虎午夜剧场 | 亚洲免费美女视频 |