Golang系列之為什么你能這么丑(一)

logo-go.png

老規(guī)矩,開始學(xué)習(xí)新編程語言的第一步,來個hello world咯。
要對得起go的名聲,就來個web版的hello world吧2333

package main

import (
    "fmt"
    "net/http"
)

type Hello struct{}

func (h Hello) ServeHTTP(w http.ResponseWriter,r *http.Request) {
    fmt.Fprint(w, "Hello World!")
}

func main() {
    var h Hello
    http.ListenAndServe("localhost:2333", h)
}

$ go run main.go
瀏覽器打開localhost:2333,Hello World!

hellogo.png

標新立異不是你的錯,可長得丑就是你的錯了

每一個go程序都是包,這里導(dǎo)出包名為main
package main
導(dǎo)入包,fmt用于輸入輸出,net/http用于http服務(wù)

import(
    "fmt"
    "net/http"
)

命名一個結(jié)構(gòu)體
type Hello struct{}
為Hello結(jié)構(gòu)體類型添加方法,實現(xiàn)了ServeHTTP接口

func (h Hello) ServeHTTP(w http.ResponseWriter,r *http.Request) {
    fmt.Fprint(w, "Hello World!")
}

入口函數(shù),先聲明h,再啟動http監(jiān)聽服務(wù)

func main() {
    var h Hello
    http.ListenAndServe("localhost:2333", h)
}

看完上面這一小段程序,現(xiàn)在的你什么想法?
反正我敲完hello world,是被丑哭了T T

變量聲明

包管理還算中規(guī)中矩,可聲明變量的語法,,,你看看
聲明一個int
var i int
初始化
var i int = 1

i := 1
聲明一個int指針,最后一種方式會由編譯器進行自動推導(dǎo)類型
var p *int 或 var p *int = &i 或 p := &i
是的你沒看錯,類型是放后面,和C系語言是反著來的
Golang發(fā)明者說,這樣做是因為C系語言的變量聲明方法不好,哪里不好了呢,拿函數(shù)指針舉了個栗子
聲明一個簡單的C函數(shù)指針
int (*fp)(int a, int b)
不難理解吧fp是一個函數(shù)指針,接受兩個int參數(shù),返回類型也是int。這里將fp插入聲明的類型中去,很直觀。
可是如果復(fù)雜一點,第一個參數(shù)也是個函數(shù)指針呢
int (*fp)(int (*ff)(int x, int y), int b)
將int a 替換成 int (*ff)(int x, int y)就是了,已經(jīng)有點難以直接看懂了是不是。當然可以省略變量名試一下
int (*fp)(int (*)(int ,int), int)
上面這樣還是算可以瞄一下看懂的,可是萬一,這個函數(shù)指針的返回類型也是一個函數(shù)指針呢,,,,
int (*(*fp)(int (*)(int, int), int))(int, int)
誰能一下子看懂我就服了,會出現(xiàn)這樣難以閱讀的問題,是因為C的函數(shù)指針聲明,將變量名字插入聲明類型本身中去了。這樣你就要一會從右往左讀一會又要從左往右讀

那如果是Go的話,會怎樣聲明呢
f func(func(int,int) int, int) func(int, int)int
變量名字和類型本身分開了,變量名字放前面,類型在后面,從始至終由左往右讀。func表示這是個函數(shù),括號開始,接下來func表示第一個參數(shù)也是個函數(shù),這個函數(shù)參數(shù)是兩個int,其返回類型是int,也即func(int ,int) int,接下來還有個int參數(shù),括號結(jié)束。然后是這個函數(shù)的返回類型,返回類型為func(int, int) int,即這個返回類型是接受兩個int參數(shù)返回一個int的函數(shù)。

嗯,,,看起來不明覺厲吧,我是覺得這真是品味問題,不關(guān)可讀性的事,C系語言的聲明方式挺好的,除了函數(shù)指針這一塊有點繞之外,沒其他壞處。而var i int = 1,這也太丑了點吧=。=

你的 { 放哪里

這也是個個人品味問題了吧。愛放哪放哪,
見過的大概三種

int main()
{
     if(,,,)
     {
         ,,,,,
     }
     else
     {
          ,,,,
     }
}
int main()
{
     if(,,,,,) {
         ,,,,
     }else {
         ,,,,
     }
}
int main() {
     if(,,,,,) {
          ,,,
     }else {
          ,,,
     }
}

項目中肯定要統(tǒng)一,但是語言不應(yīng)該強求程序員要用哪種,Python強制縮進都罵聲一片了,go更作死,所有 { 必須在行后,不可以另起一行!否則編譯都不讓過。幸虧我早習(xí)慣了google編程風(fēng)格那一套,對我沒影響,可是就是不開森。用哪種是一回事,能不能自由選擇又是另外一回事。我覺得Google Golang開發(fā)團隊有點將個人喜好強加給其他開發(fā)者了。

沒有類,只有接口

回過頭來看hello world
http.ListenAndServe("localhost:2333", h)
這一句做了什么呢?它綁定了一個端口,請求交給h處理,那h是個什么東西呢?是我們剛剛聲明的類型Hello,只要Hello實現(xiàn)了接口ServeHTTP,就能作為參數(shù)傳給http.ListenAndServe。
在package http中,這個接口是這樣定義的

package http

type Handler interface {
  ServeHTTP(w ResponseWriter, r *Request)
}

然后我們?yōu)镠ello 實現(xiàn)這個接口,http.ResponseWrite和http,Request由http.Handler負責(zé)傳入,我們只要將"Hello World!"寫入ResponseWrite中就好了。

func (h Hello) ServeHTTP(w http.ResponseWriter,r *http.Request) {
    fmt.Fprint(w, "Hello World!")
}

如果你寫過其他語言的類似http服務(wù),就會知道這完全是兩個世界的東西啊。。。丑不丑見仁見智咯。

關(guān)于Golang系列

最近在學(xué)Golang,想把所學(xué)的整理出來成為一個系列,這是第一篇。hello world入門級別。
語法不會細說,主要寫Go的并發(fā)處理。這也是Golang的主戰(zhàn)場。

感覺Golang作為工程語言是合適的,尤其在后端開發(fā),高并發(fā)的應(yīng)用場景很是適合,加上編譯完成就是二進制包,不需要像python或者java那樣另外裝運行壞境,部署方便。而且性能也是6666的,Golang = C++的性能 + Python的開發(fā)效率,畢竟Google是它爹啊。而對于語言本身呢,除了并發(fā)原生支持那一塊,就乏善可陳了,離學(xué)院派很是遙遠??墒强墒?,又有C++的性能,又有Python的開發(fā)效率,顏值是低了點,可還是能讓人喜歡上的哈哈哈哈。

先挖坑在這里了,如果有想看的,點個贊我盡快寫哈 =。=


原文轉(zhuǎn)自謝培陽的博客

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容