Goland支持泛型了(上機(jī)實(shí)操)
事情出因
一大早上被一篇公眾號(hào)的推文震驚了,Goland竟然支持go的泛型了。據(jù)我所知:
Go的泛型不是還在設(shè)計(jì)草圖嗎?最樂觀估計(jì)也要2021年8月份。你說Go語(yǔ)言現(xiàn)在都沒開發(fā)好泛型,你支持這個(gè)特性有什么用呢?
帶著好奇心點(diǎn)開推文,沒發(fā)現(xiàn)對(duì)泛型的說明,只看到一個(gè)Goland對(duì)泛型的使用的說明鏈接: https://blog.jetbrains.com/go/2020/11/24/experimenting-with-go-type-parameters-generics-in-goland/,心里怪癢癢的,忍不住點(diǎn)開看了,恍然大悟。
雖然Go并沒有完整實(shí)現(xiàn)好泛型,但是卻有個(gè)go2go工具的build工具,能把泛型代碼編譯成二進(jìn)制可執(zhí)行文件。話不多說,試試它。
準(zhǔn)備和我的環(huán)境
- 下載現(xiàn)在最新的Goland工具:2020.3
- macos Big Sur 系統(tǒng)
- git version 2.21.0
- 你可能要科學(xué)上網(wǎng)
上機(jī)實(shí)操
大致流程如下:
- 檢出最新的Go代碼的泛型實(shí)現(xiàn)的分支
- 編譯該分支得到一些工具,用來支持泛型
- 在Goland里面配置泛型編譯工具
科學(xué)拉取go源碼
由于Go的源碼的git倉(cāng)庫(kù)地址是https://go.googlesource.com/go,卻不在GitHub上,這就有點(diǎn)頭疼了。所以前提是你有科學(xué)上網(wǎng)工具。
我介紹下我的步驟。
1.查看你本地代理的代理端口,如我的端口是1087,所以我在我讓我的終端也會(huì)走代理,因?yàn)橐话銇碚f科學(xué)上網(wǎng)工具只會(huì)代理瀏覽器。
export http_proxy=http://127.0.0.1:1087;export https_proxy=http://127.0.0.1:1087;
然后檢出https://go.googlesource.com/go到go-mainline目錄,并切換分支到
git clone https://go.googlesource.com/go go-mainline
3.此時(shí)用Goland打開該go源碼,檢出分支dev.go2go。


4.然后為Goland配置些環(huán)境變量
①、在Settings/Preferences | Go | GOROOT, 選擇No SDK 選項(xiàng)
②、在Settings/Preferences | Tools | Terminal, 添加下面的環(huán)境變量:GOROOT_BOOTSTRAP為版本大于1.14的Go sdk(我直接用的是1.15)、CGO_ENABLED=0


5.然后在Goland的控制臺(tái)下,進(jìn)入到源碼的src下,執(zhí)行
bash make.bash
如果你是windows系統(tǒng),那么就用bash.bat。
然后等待一會(huì)兒,你能明顯聽見CPU風(fēng)扇的聲音。
6.上面工具都編譯好只有,接下來就新建個(gè)項(xiàng)目試一下吧,下面我就拋磚引玉了。

上面是我新建的一個(gè)項(xiàng)目,如果你的代碼的后綴不是.go2的話請(qǐng)改成.go2,.go2就表示里面用了go2的語(yǔ)法,也就包括了泛型,這里我測(cè)試泛型。(看后綴就能看出來官方的決心了,go2一定是會(huì)有泛型的)
7.此時(shí)還沒完,可以給Goland加個(gè)快捷工具,當(dāng)然也可以不加在命令行執(zhí)行,把go2泛型代碼編譯成二進(jìn)制文件,到時(shí)候我們就可以執(zhí)行該二進(jìn)制文件查看泛型代碼的結(jié)果。
program我這里是Users/shen/go-mainline/go,這個(gè)就是我上面拉取go的源碼編譯得到的。

在這里就會(huì)找到這個(gè)命令,執(zhí)行他就會(huì)獲得編譯好的二進(jìn)制文件。

8.最后在命令行就能獲得結(jié)果。

9.說說我體驗(yàn)下來Goland的感受:
①、并沒有想象中那么好用,甚至連最簡(jiǎn)單的使用都?jí)騿埽缈次业慕貓D,它最any的關(guān)鍵字都提示不支持,你說這。。。
②、當(dāng)我要運(yùn)行泛型代碼的時(shí)候,還需要自己配置編譯工具,這種體驗(yàn)我覺得就沒必要說支持了吧,難道是我還沒有使用對(duì),可是我明明按照官方的文檔來操作的啊。
說說對(duì)泛型的理解
下面是我的泛型測(cè)試代碼:
package main
import "fmt"
type Book struct {
Name string
Price int
}
func (x Book) Less(y Book) bool {
return y.Price < x.Price
}
type Lesser[T any] interface {
Less(y T) bool
}
func doSort[T Lesser[T]](a []T) {
for i := 0; i < len(a)-1; i++ {
for j := i; j < len(a); j++ {
if a[i].Less(a[j]) {
a[i], a[j] = a[j], a[i]
}
}
}
}
func main() {
a := []Book{
{"Second Book", 2},
{"First Book", 1},
{"Fifth Book", 5},
{"Fourth Book", 4},
{"Sixth Book", 6},
{"Third Book", 3},
{"shen", 8},
}
doSort(a)
fmt.Println(a)
}
Lesser是Book實(shí)現(xiàn)的接口,所謂泛型就是接口里面可以不把方法的返回參數(shù),請(qǐng)求參數(shù)固定死,這個(gè)和java的泛型一致,編譯階段是不知道具體參數(shù)類型的,只有在運(yùn)行時(shí)才知道具體的參數(shù)類型。Lesser的方法Less(y T) bool的參數(shù)類型是T,然后Book實(shí)現(xiàn)該方法就要指定具體參數(shù)類型了func (x Book) Less(y Book) bool,這里就是Book類型。
然后調(diào)用方法理解起來和java的泛型意思差不多了:func doSort[T Lesser[T]](a []T),下面是我用java實(shí)現(xiàn)相同功能的的泛型:
package com.shen.main;
public class Main {
public static void main(String[] args) {
Book[] a = new Book[]{
new Book("Second Book", 2),
new Book("First Book", 1),
new Book("Fifth Book", 5),
new Book("Fourth Book", 4),
new Book("Sixth Book", 6),
new Book("Third Book", 3)
};
doSort(a);
for (Book book : a) {
System.out.println(book);
}
}
public static <T extends Lesser<T>> void doSort(T[] a) {
for (int i = 0; i < a.length; i++) {
for (int j = i; j < a.length; j++) {
if (a[i].Less(a[j])) {
T temp = a[i];
a[i] = a[j];
a[j] = temp;
}
}
}
}
}
interface Lesser<T> {
boolean Less(T y);
}
class Book implements Lesser<Book> {
String name;
int price;
public Book(String name, int price) {
this.name = name;
this.price = price;
}
@Override
public String toString() {
return "Book{" +
"name='" + name + '\'' +
", price=" + price +
'}';
}
@Override
public boolean Less(Book y) {
return y.price < this.price;
}
}
大家對(duì)照下看看,是不是和java的何其相似,所以我覺得網(wǎng)上有些人一邊期盼著泛型能徹底改變go的大型工程結(jié)構(gòu),一邊又怕泛型引來一些維護(hù)成本,覺得增加了go的難度。我覺得這個(gè)擔(dān)心完全沒必要,只要你對(duì)java的泛型或者其他語(yǔ)言的泛型稍微有點(diǎn)基礎(chǔ),就很容易看懂,所有泛型的目的都差不多,只不過是換湯不換藥而已(看到有些人還在爭(zhēng)論go的泛型是用尖括號(hào)還是小括號(hào)還是中括號(hào)而引發(fā)的感嘆)。
總結(jié)
好了以上就是我對(duì)Goland的泛型支持的體驗(yàn)過程,對(duì)Goland的泛型支持很失望,也許一開始就抱有了很好的期待了吧,但是對(duì)Goland的行動(dòng)很佩服,我相信在Go的泛型正式實(shí)現(xiàn)之后,Goland一定會(huì)很好的支持的。
還有就是體驗(yàn)了下泛型的力量,確實(shí)減少了很多工作量,代碼更簡(jiǎn)潔。留給大家想想: 如果不用泛型go的代碼怎么實(shí)現(xiàn),有多臃腫呢?起碼Lesser接口里面的方法要為每個(gè)具體入?yún)⒍x一個(gè)方法,而且方法名還不能一樣,尼瑪。。。,最最重要的是解耦性還不好:接口耦合了具體參數(shù)類型。。。
上面就是我的感受,我也就是入個(gè)門,還沒有更加深入的體驗(yàn)go的泛型草圖設(shè)計(jì),如果你也感興趣的話,可以看看go的泛型設(shè)計(jì)文檔:https://go.googlesource.com/proposal/+/refs/heads/master/design/go2draft-type-parameters.md
到此這篇關(guān)于Goland支持泛型了(上機(jī)實(shí)操)的文章就介紹到這了,更多相關(guān)Goland泛型內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Golang初始化MySQL數(shù)據(jù)庫(kù)方法淺析
這篇文章主要介紹了Golang初始化MySQL數(shù)據(jù)庫(kù)的方法,數(shù)據(jù)庫(kù)的建立第一步即要初始化,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)吧2023-05-05
Go標(biāo)準(zhǔn)庫(kù)http?server的優(yōu)雅關(guān)閉深入理解
這篇文章主要為大家介紹了Go標(biāo)準(zhǔn)庫(kù)http?server的優(yōu)雅有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪關(guān)閉深入理解2024-01-01
關(guān)于golang中map使用的幾點(diǎn)注意事項(xiàng)總結(jié)(強(qiáng)烈推薦!)
map是一種無序的基于key-value的數(shù)據(jù)結(jié)構(gòu),Go語(yǔ)言中的map是引用類型,必須初始化才能使用,下面這篇文章主要給大家介紹了關(guān)于golang中map使用的幾點(diǎn)注意事項(xiàng),需要的朋友可以參考下2023-01-01
Go語(yǔ)言模型:string的底層數(shù)據(jù)結(jié)構(gòu)與高效操作詳解
這篇文章主要介紹了Go語(yǔ)言模型:string的底層數(shù)據(jù)結(jié)構(gòu)與高效操作詳解,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2020-12-12
使用GO實(shí)現(xiàn)Paxos共識(shí)算法的方法
這篇文章主要介紹了使用GO實(shí)現(xiàn)Paxos共識(shí)算法,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作,具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-09-09
sublime text3解決Gosublime無法自動(dòng)補(bǔ)全代碼的問題
本文主要介紹了sublime text3解決Gosublime無法自動(dòng)補(bǔ)全代碼的問題,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-01-01

