中文字幕在线观看,亚洲а∨天堂久久精品9966,亚洲成a人片在线观看你懂的,亚洲av成人片无码网站,亚洲国产精品无码久久久五月天

Golang的演化歷程

2018-07-20    來(lái)源:編程學(xué)習(xí)網(wǎng)

容器云強(qiáng)勢(shì)上線!快速搭建集群,上萬(wàn)Linux鏡像隨意使用

  本文來(lái)自Google的Golang語(yǔ)言設(shè)計(jì)者之一Rob Pike大神在GopherCon2014大會(huì)上的開(kāi)幕主題演講資料“Hello, Gophers!”。Rob大神在這次分 享中用了兩個(gè)生動(dòng)的例子講述了Golang的演化歷程,總結(jié)了Golang到目前為止的成功因素,值得廣大Golang Programmer & Beginner學(xué)習(xí)和了解。這里也用了”Golang的演化歷程”作為標(biāo)題。

  1、Hello Gophers!

package main

import "fmt"

func main() {
    fmt.Printf("Hello, gophers!\n")
}

  Rob大神的見(jiàn)面禮,后續(xù)會(huì)有針對(duì)這段的演化歷史的陳述。

  2、歷史

  這是一個(gè)歷史性的時(shí)刻。

  Golang已經(jīng)獲得了一定的成功,值得擁有屬于自己的技術(shù)大會(huì)。

  3、成功

  促成這份成功的因素有許多:

  – 功能
  – 缺少的功能
  – 功能的組合
  – 設(shè)計(jì)
  – 人
  – 時(shí)間

  4、案例學(xué)習(xí):兩段程序

  我們來(lái)近距離回顧兩段程序。

  第一個(gè)是你見(jiàn)過(guò)的第一個(gè)Go程序,是屬于你的歷史時(shí)刻。

  第二個(gè)是我們見(jiàn)過(guò)的第一個(gè)Go程序,是屬于全世界所有Gophers的歷史時(shí)刻。

  先看第一個(gè)“hello, world”

  5、hello.b

main( ) {
    extrn a, b, c;
    putchar(a); putchar(b); putchar(c); putchar('!*n');
}
a 'hell';
b 'o, w';
c 'orld';

  上面這段代碼首先出現(xiàn)在1972年Brian W. Kernighan的B語(yǔ)言教程中(也有另外一說(shuō)是出現(xiàn)在那之前的BCPL語(yǔ)言中)。

  6、hello.c

main()
{
    printf("hello, world");
}

  上面這段代碼出現(xiàn)在1974年Brian W. Kernighan編寫(xiě)的《Programming in C: A Tutorial》中。這份教程當(dāng)時(shí)是作為Unix v5文檔的一部分。

  7、hello.c

main()
{
    printf("hello, world\n"); //譯注:與上面的hello.c相比,多了個(gè)換行符\n輸出
}

  這段代碼首次出現(xiàn)在1978年Brian W. Kernighan和Dennis M. Ritchie合著的《The C Programming Language》一書(shū)中。

  8、hello.c, 標(biāo)準(zhǔn)C草案

#include <stdio.h> //譯注:與上面hello.c相比, 多了這個(gè)頭文件包含

main()
{
    printf("hello, world\n");
}

  這段代碼出現(xiàn)在1988年Brian W. Kernighan和Dennis M. Ritchie合著的《The C Programming Language》第二版一書(shū)中,基于標(biāo)準(zhǔn)C草案。

  9、hello.c,標(biāo)準(zhǔn)C89

#include <stdio.h>

main(void) //譯注:與上面hello.c相比,多了個(gè)void
{
    printf("hello, world\n");
}

  這段代碼出現(xiàn)在1988年Brian W. Kernighan和Dennis M. Ritchie合著的《The C Programming Language》第二版第二次修訂中。

  10、一兩代之后…

  (省略所有中間語(yǔ)言)

  關(guān)于Golang的討論開(kāi)始于2007年年末。

  第一版語(yǔ)言規(guī)范起草于2008年3月份。

  用于實(shí)驗(yàn)和原型目的的編譯器開(kāi)發(fā)工作已經(jīng)展開(kāi)。

  最初的編譯器輸出的是C代碼。

  語(yǔ)言規(guī)范一形成,我們就重寫(xiě)了編譯器,輸出本地代碼(機(jī)器碼)。

  11、hello.go, 2008年6月6日

package main

func main() int {
    print "hello, world\n";
    return 0;
}

  12、hello.go,2008年6月27日

package main

func main() {
    print "hello, world\n";
}

  當(dāng)main函數(shù)返回,程序調(diào)用exit(0)。

  13、hello.go,2008年8月11日

package main

func main() {
    print("hello, world\n");
}

  print調(diào)用加上了括號(hào),這時(shí)print是一個(gè)函數(shù),不再是一個(gè)原語(yǔ)。

  14、hello.go,2008年10月24日

package main

import "fmt"

func main() {
    fmt.printf("hello, world\n");
}

  我們熟知并喜歡的printf來(lái)了。

  15、hello.go,2009年1月15日

package main

import "fmt"

func main() {
    fmt.Printf("hello, world\n");
}

  頭母大寫(xiě)的函數(shù)名用作才是導(dǎo)出的符號(hào)。

  16、hello.go, 2009年12約11日

package main

import "fmt"

func main() {
    fmt.Printf("hello, world\n")
}

  不再需要分號(hào)。

  這是在2009年11月10日Golang開(kāi)發(fā)發(fā)布后的一次重要改變。

  這也是當(dāng)前版本的hello, world

  我們花了些時(shí)間到達(dá)這里(32年。

  都是歷史了!

  17、不僅僅有C

  我們從”C”開(kāi)始,但Go與C相比有著巨大的不同。

  其他一些語(yǔ)言影響和貫穿于Go的設(shè)計(jì)當(dāng)中。

  C: 語(yǔ)句和表達(dá)式語(yǔ)法
  Pascal: 聲明語(yǔ)法
  Modula 2, Oberon 2:包
  CSP, Occam, Newsqueak, Limbo, Alef:  并發(fā)
  BCPL: 分號(hào)規(guī)則
  Smalltalk: 方法(method)
  Newsqueak: <-, :=
  APL: iota

  等等。也有一些是全新發(fā)明的,例如defer、常量。

  還有一些來(lái)自其他語(yǔ)言的優(yōu)點(diǎn)和缺點(diǎn):

  C++, C#, Java, JavaScript, LISP, Python, Scala, …

  18、hello.go,Go 1版

  將我們帶到了今天。

package main

import "fmt"

func main() {
    fmt.Println("Hello, Gophers (some of whom know 中文)!")
}

  我們來(lái)深入挖掘一下,把這段代碼做一個(gè)拆解。

  19、Hello, World的16個(gè)tokens

package
main
import
"fmt"
func
main
(
)
{
fmt
.
Println
(
"Hello, Gophers (some of whom know 中文)!"
)
}

  20、package

  早期設(shè)計(jì)討論的主要話題:擴(kuò)展性的關(guān)鍵

  package是什么?來(lái)自Modula-2等語(yǔ)言的idea

  為什么是package?

  – 擁有編譯構(gòu)建所需的全部信息
  – 沒(méi)有循環(huán)依賴(import)
  – 沒(méi)有子包
  – 包名與包路徑分離
  – 包級(jí)別可見(jiàn)性,而不是類型級(jí)別
  – 在包內(nèi)部,你擁有整個(gè)語(yǔ)言,在包外部,你只擁有包許可的東西。

  21、main

  一個(gè)C語(yǔ)言遺留風(fēng)范盡顯之處

  最初是Main,原因記不得了。

  主要的包,main函數(shù)

  很特別,因?yàn)樗浅跏蓟瘶?shù)(initialization tree)的根(root)。

  22、import

  一種加載包的機(jī)制

  通過(guò)編譯器實(shí)現(xiàn)(有別于文本預(yù)處理器。譯注:C語(yǔ)言的include是通過(guò)preprocessor實(shí)現(xiàn)的)

  努力使其高效且線性

  導(dǎo)入的一個(gè)包,而不是一個(gè)標(biāo)識(shí)符(identifiers)集合(譯注:C語(yǔ)言的include是將頭文件里的標(biāo)識(shí)符集合引入)

  至于export,它曾經(jīng)是一個(gè)關(guān)鍵字。

  23、”fmt”

  包路徑(package path)只是一個(gè)字符串,并非標(biāo)識(shí)符的列表。

  讓語(yǔ)言避免定義它的含義 – 適應(yīng)性。(Allows the language to avoid defining what it means—adaptability)

  從一開(kāi)始就想要一個(gè)URL作為一個(gè)選項(xiàng)。(譯注:類似import “github.com/go/tools/xxx)

  可以應(yīng)付將來(lái)的發(fā)展。

  24、func

  一個(gè)關(guān)鍵字,用于引入函數(shù)(類型、變量、常量),易于編譯器解析。

  對(duì)于函數(shù)字面量(閉包)而言,易于解析非常重要。

  順便說(shuō)一下,最初這個(gè)關(guān)鍵字不是func,而是function。

  小插曲:

Mail thread from February 6, 2008
From: Ken Thompson <[email protected]>
To: gri, r
larry and sergey came by tonight. we ?talked about go for more than an hour. ?they both said they liked it very much.
p.s. one of larrys comments was “why isnt function spelled func?”

From: Rob Pike <[email protected]>
To: ken, gri
fine with me. seems compatible with ‘var’.
anyway we can always say, “larry said to call it ‘func’”

  25、main

  程序執(zhí)行的起點(diǎn)。除非它不是。(譯注:main不是起點(diǎn),rob大神的意思是不是指下列情形,比如go test測(cè)試包,在google app engine上的go程序不需要main)

  將初始化與正常執(zhí)行分離,早期計(jì)劃之中的。

  初始化在哪里發(fā)生的?(譯注:說(shuō)的是package內(nèi)的func init() {..}函數(shù)吧)

  回到包設(shè)計(jì)。(譯注:重溫golang的package設(shè)計(jì)思想)

  26、()

  看看,沒(méi)有void

  main沒(méi)有返回值,由運(yùn)行時(shí)來(lái)處理main的返回后的事情。

  沒(méi)有函數(shù)參數(shù)(命令行選項(xiàng)通過(guò)os包獲。

  沒(méi)有返回值

  返回值以及語(yǔ)法

  27、{

  用的是大括號(hào),而不是空格(譯注:估計(jì)是與python的空格縮進(jìn)對(duì)比)

  同樣也不是方括號(hào)。

  為什么在括號(hào)后放置換行符(newline)?

  28、fmt

  所有導(dǎo)入的標(biāo)識(shí)符均限定于其導(dǎo)入的包。(All imported identifiers are qualified by their import.)

  每個(gè)標(biāo)識(shí)符要么是包或函數(shù)的本地變量,要么被類型或?qū)氚薅ā?/p>

  對(duì)代碼可讀性的重大影響。

  為什么是fmt,而不是format?

  29、.

  句號(hào)token在Go中有多少使用?(很多)

  a.B的含義需要使用到類型系統(tǒng)

  但這對(duì)于人類來(lái)說(shuō)非常清晰,讀起來(lái)也非常容易。

  針對(duì)指針的自動(dòng)轉(zhuǎn)換(沒(méi)有->)。

  30、Println

  Println,不是println,頭母大寫(xiě)才是導(dǎo)出符號(hào)。

  知道它是反射驅(qū)動(dòng)的(reflection-driven)

  可變參數(shù)函數(shù)

  參數(shù)類型是(…); 2010年2月1日變成(…interface{})

  31、(

  傳統(tǒng)函數(shù)語(yǔ)法

  32、”Hello, Gophers (some of whom know 中文)!”

  UTF-8編碼的源碼輸入。字符串字面量也自動(dòng)是utf8編碼格式的。

  但什么是字符串(string)呢?

  首批寫(xiě)入規(guī)范的語(yǔ)法規(guī)則,今天很難改變了。(blog.golang.org/strings)

  33、)

  沒(méi)有分號(hào)

  在go發(fā)布后不久我們就去除了分號(hào)

  早期曾胡鬧地嘗試將它們(譯注:指得是括號(hào))去掉

  最終接受了BCPL的方案

  34、}

  第一輪結(jié)束。

  旁白:還沒(méi)有討論到的

  – 類型
  – 常量
  – 方法
  – interface
  – 庫(kù)
  – 內(nèi)存管理
  – 并發(fā)(接下來(lái)將討論)

  外加工具,生態(tài)系統(tǒng),社區(qū)等。

  語(yǔ)言是核心,但也只是我們故事的一部分。

  35、成功

  要素:
  – 站在巨人的肩膀上(building on history)
  – 經(jīng)驗(yàn)之作(building on experience) 譯注:最初的三個(gè)神級(jí)語(yǔ)言設(shè)計(jì)者
  – 設(shè)計(jì)過(guò)程
  – 早期idea提煉到最終的方案中
  – 由一個(gè)小團(tuán)隊(duì)專門(mén)集中精力做

  最終:承諾
  Go 1.0鎖定了語(yǔ)言核心與標(biāo)準(zhǔn)庫(kù)。

  36、另一輪

  讓我們看第二個(gè)程序的類似演化過(guò)程。

  37、問(wèn)題:素?cái)?shù)篩(Prime sieve)

  問(wèn)題來(lái)自于Communicating Sequential Processes, by C. A. R. Hoare, 1978。

  “問(wèn)題:以升序打印所有小于10000的素?cái)?shù)。使用一個(gè)process數(shù)組:SIEVE,其中每個(gè)process從其前驅(qū)元素輸入一個(gè)素?cái)?shù)并打印它。接下 來(lái)這個(gè)process從其前驅(qū)元素接收到一個(gè)升序數(shù)字流并將它們傳給其后繼元素,這個(gè)過(guò)程會(huì)剔除掉所有是最初素?cái)?shù)整數(shù)倍的數(shù)字。

  38、解決方案

  在1978年的CSP論文中。(注意不是Eratosthenes篩)

  這個(gè)優(yōu)美的方案是由David Gries貢獻(xiàn)出來(lái)的。

  39、CSP

  在Hoare的CSP論文中:

[SIEVE(i:1..100)::
    p,mp:integer;
    SIEVE(i - 1)?p;
    print!p;
    mp := p; comment mp is a multiple of p;
*[m:integer; SIEVE(i - 1)?m →
    *[m > mp → mp := mp + p];
    [m = mp → skip
    ||m < mp → SIEVE(i + 1)!m
]   ]
||SIEVE(0)::print!2; n:integer; n := 3;
    *[n < 10000 → SIEVE(1)!n; n := n + 2]
||SIEVE(101)::*[n:integer;SIEVE(100)?n → print!n]
||print::*[(i:0..101) n:integer; SIEVE(i)?n → ...]
]

  沒(méi)有channel。能處理的素?cái)?shù)的個(gè)數(shù)是在程序中指定的。

  40、Newsqueak

  circa 1988。

  Rob Pike語(yǔ)言設(shè)計(jì),Tom Cargill和Doug McIlroy實(shí)現(xiàn)。

  使用了channels,這樣個(gè)數(shù)是可編程的。(channel這個(gè)idea從何而來(lái)?)

counter:=prog(end: int, c: chan of int)
{
    i:int;
    for(i=2; i<end; i++)
        c<-=i;
};

filter:=prog(prime: int, listen: chan of int, send: chan of int)
{
    i:int;
    for(;;)
        if((i=<-listen)%prime)
            send<-=i;
};

sieve:=prog(c: chan of int)
{
    for(;;){
        prime:=<-c;
        print(prime, " ");
        newc:=mk(chan of int);
        begin filter(prime, c, newc);
        c=newc;
    }
};

count:=mk(chan of int);

begin counter(10000, count);
begin sieve(count);
"";

  41、sieve.go,2008年3月5日

  使用go規(guī)范編寫(xiě)的第一個(gè)版本,可能是第二個(gè)由go編寫(xiě)的重要程序。

  >用于發(fā)送;<用于接收。Channel是指針。Main是頭字母大寫(xiě)的。

package Main

// Send the sequence 2, 3, 4, … to channel 'ch'.
func Generate(ch *chan> int) {
    for i := 2; ; i++ {
        >ch = i;    // Send 'i' to channel 'ch'.
    }
}

// Copy the values from channel 'in' to channel 'out',
// removing those divisible by 'prime'.
func Filter(in *chan< int, out *chan> int, prime int) {
    for ; ; {
        i := <in;    // Receive value of new variable 'i' from 'in'.
        if i % prime != 0 {
            >out = i;    // Send 'i' to channel 'out'.
        }
    }
}

// The prime sieve: Daisy-chain Filter processes together.
func Sieve() {
    ch := new(chan int);  // Create a new channel.
    go Generate(ch);      // Start Generate() as a subprocess.
    for ; ; {
        prime := <ch;
        printf("%d\n", prime);
        ch1 := new(chan int);
        go Filter(ch, ch1, prime);
        ch = ch1;
    }
}

func Main() {
    Sieve();
}

  42. sieve.go,2008年7月22日

  -<用于發(fā)送;-<用于接收。Channel仍然是指針。但現(xiàn)在main不是大寫(xiě)字母開(kāi)頭的了。

package main

// Send the sequence 2, 3, 4, … to channel 'ch'.
func Generate(ch *chan-< int) {
    for i := 2; ; i++ {
        ch -< i    // Send 'i' to channel 'ch'.
    }
}

// Copy the values from channel 'in' to channel 'out',
// removing those divisible by 'prime'.
func Filter(in *chan<- int, out *chan-< int, prime int) {
    for {
        i := <-in;    // Receive value of new variable 'i' from 'in'.
        if i % prime != 0 {
            out -< i    // Send 'i' to channel 'out'.
        }
    }
}

// The prime sieve: Daisy-chain Filter processes together.
func Sieve() {
    ch := new(chan int);  // Create a new channel.
    go Generate(ch);      // Start Generate() as a subprocess.
    for {
        prime := <-ch;
        printf("%d\n",    prime);
        ch1 := new(chan int);
        go Filter(ch, ch1, prime);
        ch = ch1
    }
}

func main() {
    Sieve()
}

  43、sieve.go,2008年9月17日

  通信操作符現(xiàn)在是<-。channel仍然是指針。

package main

// Send the sequence 2, 3, 4, … to channel 'ch'.
func Generate(ch *chan <- int) {
    for i := 2; ; i++ {
        ch <- i  // Send 'i' to channel 'ch'.
    }
}

// Copy the values from channel 'in' to channel 'out',
// removing those divisible by 'prime'.
func Filter(in *chan <- int, out *<-chan int, prime int) {
    for {
        i := <-in;  // Receive value of new variable 'i' from 'in'.
        if i % prime != 0 {
            out <- i  // Send 'i' to channel 'out'.
        }
    }
}

// The prime sieve: Daisy-chain Filter processes together.
func Sieve() {
    ch := new(chan int);  // Create a new channel.
    go Generate(ch);      // Start Generate() as a subprocess.
    for {
        prime := <-ch;
        print(prime, "\n");
        ch1 := new(chan int);
        go Filter(ch, ch1, prime);
        ch = ch1
    }
}

func main() {
    Sieve()
}

  44、sieve.go,2009年1月6日

 引入了make內(nèi)置操作符。沒(méi)有指針。編碼錯(cuò)誤。ㄓ袀(gè)*被留下了,錯(cuò)誤的參數(shù)類型)

package main

// Send the sequence 2, 3, 4, … to channel 'ch'.
func Generate(ch chan <- int) {
    for i := 2; ; i++ {
        ch <- i  // Send 'i' to channel 'ch'.
    }
}

// Copy the values from channel 'in' to channel 'out',
// removing those divisible by 'prime'.
func Filter(in chan <- int, out *<-chan int, prime int) {
    for {
        i := <-in;  // Receive value of new variable 'i' from 'in'.
        if i % prime != 0 {
            out <- i  // Send 'i' to channel 'out'.
        }
    }
}

// The prime sieve: Daisy-chain Filter processes together.
func Sieve() {
    ch := make(chan int);  // Create a new channel.
    go Generate(ch);       // Start Generate() as a subprocess.
    for {
        prime := <-ch;
        print(prime, "\n");
        ch1 := make(chan int);
        go Filter(ch, ch1, prime);
        ch = ch1
    }
}

func main() {
    Sieve()
}

  45、sieve.go,2009年9月25日

  第一個(gè)正確的現(xiàn)代版本。同樣,大寫(xiě)頭母不見(jiàn)了,使用了fmt。

package main

import "fmt"

// Send the sequence 2, 3, 4, … to channel 'ch'.
func generate(ch chan<- int) {
    for i := 2; ; i++ {
        ch <- i;    // Send 'i' to channel 'ch'.
    }
}

// Copy the values from channel 'in' to channel 'out',
// removing those divisible by 'prime'.
func filter(src <-chan int, dst chan<- int, prime int) {
    for i := range src {    // Loop over values received from 'src'.
        if i%prime != 0 {
            dst <- i;    // Send 'i' to channel 'dst'.
        }
    }
}

// The prime sieve: Daisy-chain filter processes together.
func sieve() {
    ch := make(chan int);  // Create a new channel.
    go generate(ch);       // Start generate() as a subprocess.
    for {
        prime := <-ch;
        fmt.Print(prime, "\n");
        ch1 := make(chan int);
        go filter(ch, ch1, prime);
        ch = ch1;
    }
}

func main() {
    sieve();
}

  46、sieve.go,2009年12月10日

  分號(hào)不見(jiàn)了。程序已經(jīng)與現(xiàn)在一致了。

package main

import "fmt"

// Send the sequence 2, 3, 4, … to channel 'ch'.
func generate(ch chan<- int) {
    for i := 2; ; i++ {
        ch <- i  // Send 'i' to channel 'ch'.
    }
}

// Copy the values from channel 'src' to channel 'dst',
// removing those divisible by 'prime'.
func filter(src <-chan int, dst chan<- int, prime int) {
    for i := range src {  // Loop over values received from 'src'.
        if i%prime != 0 {
            dst <- i  // Send 'i' to channel 'dst'.
        }
    }
}

// The prime sieve: Daisy-chain filter processes together.
func sieve() {
    ch := make(chan int)  // Create a new channel.
    go generate(ch)       // Start generate() as a subprocess.
    for {
        prime := <-ch
        fmt.Print(prime, "\n")
        ch1 := make(chan int)
        go filter(ch, ch1, prime)
        ch = ch1
    }
}

func main() {
    sieve()
}

  這個(gè)優(yōu)美的方案來(lái)自于幾十年的設(shè)計(jì)過(guò)程。

  47、旁邊,沒(méi)有討論到的

  select

  真實(shí)并發(fā)程序的核心連接器(connector)

  最初起源于Dijkstra的守衛(wèi)命令(guarded command)

  在Hoare的CSP理論實(shí)現(xiàn)真正并發(fā)。

  經(jīng)過(guò)Newsqueak、Alef、Limbo和其他語(yǔ)言改良后

  2008年3月26日出現(xiàn)在Go版本中。

  簡(jiǎn)單,澄清,語(yǔ)法方面的考慮。

  48、穩(wěn)定性

  Sieve程序自從2009年末就再未改變過(guò)。– 穩(wěn)定!

  開(kāi)源系統(tǒng)并不總是兼容和穩(wěn)定的。

  但,Go是。(兼容和穩(wěn)定的)

  這是Go成功的一個(gè)重要原因。

  49、趨勢(shì)

  圖數(shù)據(jù)展示了Go 1.0發(fā)布后Go語(yǔ)言的爆發(fā)。

  50、成功

  Go成功的元素:

  顯然的:功能和工具。

  * 并發(fā)
  * 垃圾回收
  * 高效的實(shí)現(xiàn)
  * 給人以動(dòng)態(tài)類型體驗(yàn)的靜態(tài)類型系統(tǒng)
  * 豐富但規(guī)模有限的標(biāo)準(zhǔn)庫(kù)
  * 工具化
  * gofmt
  * 在大規(guī)模系統(tǒng)中的應(yīng)用

  不那么顯然的:過(guò)程

  * 始終聚焦最初的目標(biāo)
  * 在凍結(jié)后的集中開(kāi)發(fā)
  * 小核心團(tuán)隊(duì)易于取得一致
  * 社區(qū)的重要貢獻(xiàn)
  * 豐富的生態(tài)系統(tǒng)

  總之,開(kāi)源社區(qū)共享了我們的使命,聚焦于為當(dāng)今的世界設(shè)計(jì)一門(mén)語(yǔ)言。

標(biāo)簽: Google isp 代碼 通信

版權(quán)申明:本站文章部分自網(wǎng)絡(luò),如有侵權(quán),請(qǐng)聯(lián)系:west999com@outlook.com
特別注意:本站所有轉(zhuǎn)載文章言論不代表本站觀點(diǎn)!
本站所提供的圖片等素材,版權(quán)歸原作者所有,如需使用,請(qǐng)與原作者聯(lián)系。

上一篇:你最深愛(ài)的編程語(yǔ)言其實(shí)很爛

下一篇:為什么35歲的C++依然能主導(dǎo)編程世界