主頁 >  其他 > golang的介面快把我給整瘋了。

golang的介面快把我給整瘋了。

2020-09-23 09:20:57 其他

有點編程基礎的我自學了一段時間go語言了,一直止步在介面這一塊,知道介面的基本用法,在本包里可以靈活使用介面,但是外包使用另外一個包的介面時我真的就懵圈了,根本不知道哪個結構體實作了哪個介面,還有兩個不是同包介面和結構體之間的賦值這一塊真的快整瘋我了,天天上語數英課啥也不聽,就自己一個人自學go,學了這么多天感覺也沒領悟介面這一塊,這個隱式實作真的太難了,根本不知道誰實作了誰?誰可以賦值給誰?現在最經典的io包下邊的writer介面和reader介面我都沒搞明白,看講師講的都太淺,就只講本包使用本包的介面和賦值,外包的就不講,一個外包(http包)介面型別和結構體之間的賦值一下子我就懵圈了,自學真的太難了,我都快撐不住了,這幾天一直專注介面這一塊的學習,但是沒太大的進展,都說go的介面是go最妙的特性,但我為啥覺得go的介面并沒有那么神,特別是這個隱式宣告,真的搞不懂誰實作了誰?大佬們可否給小弟指點迷津?小弟真的洗耳恭聽,感激不盡。

uj5u.com熱心網友回復:

介面是一種“規范”,也就是介面的實作類都要遵循這個“規范”,假如這個“規范”體現在介面的方法上,那么所有的介面實作類都要實作該介面方法(遵循“規范”,和介面一致,即介面有什么動作,實作類也有什么動作)。那么好了,如果有一個類,它封裝的方法恰好和介面定義的方法一致,也就是說它無形中遵循了介面的“規范”,所以它隱形的成了介面的實作類

打個比方,某工廠的一批零件有個生產指標,比如直徑為10cm(可以理解為有個介面方法),那么在這個工廠里生產的零件都符合這個指標,也就是都符合這個介面,因為在該工廠生產的,所以顯示地遵循了標準(也就是顯示實作介面)。那么好了,另一家工廠也生產一種零件,剛好直徑也是10cm(可以理解為有個方法和介面方法一樣)。假如我么第一家工廠生產的零件壞了,我們要找一個零件代替,我們發現另一家工廠的零件剛好也是10cm(也有同樣的介面方法),也符合第一家工廠的生產指標,所以也可以拿來代替使用。你會發現,另一家工廠沒有特意去遵循第一個工廠的指標(沒有顯示implement),但事實上卻隱式的遵循的指標,也就是說另一家工廠的零件,隱式地實作了第一家工廠的介面,所以它也和第一家工廠生產的零件一樣,能應用在相同的場合。

uj5u.com熱心網友回復:

定義一個Usb介面,Phone結構體和Mouse結構體都實作該介面,再定義一個Computer結構體,給他定義一個方法,形參型別為Usb,當傳入引數為Phone和Mouse實體的時候該方法自動識別傳入的結構體型別,并呼叫相應的方法,這應該是最經典的解釋了
關于介面我想最核心的基本就以下幾點:
實作介面中所有的方法的結構體實作該介面,甭管你哪歸哪,是不是有意的,go語言不支持多載,基本名字對上了就跑不了了
實作該介面的結構體的繼承者自動實作該介面
實作介面的繼承介面的結構體自動實作該介面
介面可以賦值給變數,結構體可以賦值給其實作的介面,賦值完了還可以通過型別斷言變回結構體變數(這是最核心的,也是最有操作性的地方)
任何結構體都默認實作空介面(根據前一點可以玩出很多騷操作)

uj5u.com熱心網友回復:

學好數語外,見人說人話,見鬼說鬼話,還是好好學習去吧,這玩意慢點來不急

uj5u.com熱心網友回復:

介面可以賦值給變數,結構體可以賦值給其實作的介面
這句話得解釋一下
首先介面本身就是一個變數型別,介面可以賦值給變數的意思是可以宣告一個該介面型別的變數,如var usb Usb
結構體賦值給介面,必須先宣告介面,然后賦值,接著上面:usb = Mouse{},或者連著寫,不可以用型別推導
另外~實作介面中所有的方法的結構體實作該介面,甭管你哪歸哪~這句話明確的說,介面和實作該介面的結構體完全可以在不同的包內

uj5u.com熱心網友回復:

參考 1 樓 qybao的回復:
介面是一種“規范”,也就是介面的實作類都要遵循這個“規范”,假如這個“規范”體現在介面的方法上,那么所有的介面實作類都要實作該介面方法(遵循“規范”,和介面一致,即介面有什么動作,實作類也有什么動作)。那么好了,如果有一個類,它封裝的方法恰好和介面定義的方法一致,也就是說它無形中遵循了介面的“規范”,所以它隱形的成了介面的實作類

打個比方,某工廠的一批零件有個生產指標,比如直徑為10cm(可以理解為有個介面方法),那么在這個工廠里生產的零件都符合這個指標,也就是都符合這個介面,因為在該工廠生產的,所以顯示地遵循了標準(也就是顯示實作介面)。那么好了,另一家工廠也生產一種零件,剛好直徑也是10cm(可以理解為有個方法和介面方法一樣)。假如我么第一家工廠生產的零件壞了,我們要找一個零件代替,我們發現另一家工廠的零件剛好也是10cm(也有同樣的介面方法),也符合第一家工廠的生產指標,所以也可以拿來代替使用。你會發現,另一家工廠沒有特意去遵循第一個工廠的指標(沒有顯示implement),但事實上卻隱式的遵循的指標,也就是說另一家工廠的零件,隱式地實作了第一家工廠的介面,所以它也和第一家工廠生產的零件一樣,能應用在相同的場合。

謝謝大佬,我自己定義的介面和結構體之間的使用我還是能搞明白的,(介面的規則我懂了)但是標準庫里邊的我就有點搞不懂了,比如
Readall( io reader)
Readall方法接收一個實作了io reader介面的引數,但是下邊的例子file怎么就變成就實作io reader介面的引數了?os. Open后回傳的應該是os. Open型別的變數,我怎么知道和確定file實作了io reader介面?講真的,我是真的看不出來file這個變數能跟io reader介面有半毛錢關系,大佬拜托您指點。

func main() { 
file, _ := os.Open("test")
 b, _ := ioutil.ReadAll(file) 
 fmt.Println(string(b)) 
}

uj5u.com熱心網友回復:

參考 4 樓 與蘤舊縐的回復:
介面可以賦值給變數,結構體可以賦值給其實作的介面
這句話得解釋一下
首先介面本身就是一個變數型別,介面可以賦值給變數的意思是可以宣告一個該介面型別的變數,如var usb Usb
結構體賦值給介面,必須先宣告介面,然后賦值,接著上面:usb = Mouse{},或者連著寫,不可以用型別推導
另外~實作介面中所有的方法的結構體實作該介面,甭管你哪歸哪~這句話明確的說,介面和實作該介面的結構體完全可以在不同的包內

謝謝大佬,我自己定義的介面和結構體之間的使用我還是能搞明白的,(介面的規則我懂了)但是標準庫里邊的我就有點搞不懂了,比如
Readall( io reader)
Readall方法接收一個實作了io reader介面的引數,但是下邊的例子file怎么就變成就實作io reader介面的引數了?os. Open后回傳的應該是os. Open型別的變數,我怎么知道和確定file實作了io reader介面?講真的,我是真的看不出來file這個變數能跟io reader介面有半毛錢關系,大佬拜托您指點。

func main() { 
file, _ := os.Open("test")
 b, _ := ioutil.ReadAll(file) 
 fmt.Println(string(b)) 
}

uj5u.com熱心網友回復:

參考 1 樓 qybao的回復:
介面是一種“規范”,也就是介面的實作類都要遵循這個“規范”,假如這個“規范”體現在介面的方法上,那么所有的介面實作類都要實作該介面方法(遵循“規范”,和介面一致,即介面有什么動作,實作類也有什么動作)。那么好了,如果有一個類,它封裝的方法恰好和介面定義的方法一致,也就是說它無形中遵循了介面的“規范”,所以它隱形的成了介面的實作類

打個比方,某工廠的一批零件有個生產指標,比如直徑為10cm(可以理解為有個介面方法),那么在這個工廠里生產的零件都符合這個指標,也就是都符合這個介面,因為在該工廠生產的,所以顯示地遵循了標準(也就是顯示實作介面)。那么好了,另一家工廠也生產一種零件,剛好直徑也是10cm(可以理解為有個方法和介面方法一樣)。假如我么第一家工廠生產的零件壞了,我們要找一個零件代替,我們發現另一家工廠的零件剛好也是10cm(也有同樣的介面方法),也符合第一家工廠的生產指標,所以也可以拿來代替使用。你會發現,另一家工廠沒有特意去遵循第一個工廠的指標(沒有顯示implement),但事實上卻隱式的遵循的指標,也就是說另一家工廠的零件,隱式地實作了第一家工廠的介面,所以它也和第一家工廠生產的零件一樣,能應用在相同的場合。

講真的標準庫里的有些型別我根本不敢確定誰實作了誰。即使知道有些方法接收一個實作了該介面型別的變數(比如Reader介面),但我又該怎么確定該型別實作了Reader介面,我也沒有實現Reader的Read方法,他實作沒實作我也不知道,就算知道這一個,但還有無數個類似的我不知道,我也不確定,我怎么能傳引數?這個隱式實作太讓我郁悶了,他也不告訴我給實作了哪個介面,我也不敢亂傳引數,我覺得這可能就是我介面這一塊搞不懂的點吧。

uj5u.com熱心網友回復:

沒懟過標準庫,不清楚這個
但有一點很簡單,你可能在某處宣告了一個介面,然后因為洋文水平有限,編不出太多方法的名字,于是反復使用某幾個名字,導致不知不覺間很多結構體都實作了那個介面
但這并不是一個問題,你的介面并不在乎有多少個結構體實作了它,你的結構體也并不在乎不知不覺間多實作了幾個介面,只需要最初的那幾對,也就是你有意實作的那幾個實作了就行
標準庫是人家寫的,人家把實作藏哪了你翻半天找不到很正常,何必管它,你又不清楚人家的分層、模式、邏輯,既然能賦值,那就是實作了
但有一點很重要,如果跨包實作介面,包丟了怎么辦,你可能哪天覺得專案哪個部分不要了,重寫,結果另外一個包內的騷操作就報錯了,這并不是說不能跨包,而是在架構設計上應當避免的問題,確保他們在一個整體中,要死一起死,要活一起活

uj5u.com熱心網友回復:

參考 7 樓 CSDN首席執行官 的回復:
講真的標準庫里的有些型別我根本不敢確定誰實作了誰。即使知道有些方法接收一個實作了該介面型別的變數(比如Reader介面),但我又該怎么確定該型別實作了Reader介面,我也沒有實作Reader的Read方法,他實作沒實作我也不知道,就算知道這一個,但還有無數個類似的我不知道,我也不確定,我怎么能傳引數?這個隱式實作太讓我郁悶了,他也不告訴我給實作了哪個介面,我也不敢亂傳引數,我覺得這可能就是我介面這一塊搞不懂的點吧。


這你要看檔案啊
Reader介面的定義
https://golang.org/pkg/io/#Reader
os.Open回傳一個File指標,File也實作了Reader介面方法
https://golang.org/pkg/os/#File.Read

go里要判斷是什么型別,可以強行轉換或者用switch

比如你的例子
file, _ := os.Open("test")
if _, ok := interface{}(file).(io.Reader); ok {
    fmt.Println("ok")
}
switch interface{}(file).(type) {
case io.Reader:
    fmt.Println("io.reader")
}

或者你用反射reflect也可以

uj5u.com熱心網友回復:

參考 9 樓 qybao的回復:
Quote: 參考 7 樓 CSDN首席執行官 的回復:

講真的標準庫里的有些型別我根本不敢確定誰實作了誰。即使知道有些方法接收一個實作了該介面型別的變數(比如Reader介面),但我又該怎么確定該型別實作了Reader介面,我也沒有實作Reader的Read方法,他實作沒實作我也不知道,就算知道這一個,但還有無數個類似的我不知道,我也不確定,我怎么能傳引數?這個隱式實作太讓我郁悶了,他也不告訴我給實作了哪個介面,我也不敢亂傳引數,我覺得這可能就是我介面這一塊搞不懂的點吧。


這你要看檔案啊
Reader介面的定義
https://golang.org/pkg/io/#Reader
os.Open回傳一個File指標,File也實作了Reader介面方法
https://golang.org/pkg/os/#File.Read

go里要判斷是什么型別,可以強行轉換或者用switch

比如你的例子
file, _ := os.Open("test")
if _, ok := interface{}(file).(io.Reader); ok {
    fmt.Println("ok")
}
switch interface{}(file).(type) {
case io.Reader:
    fmt.Println("io.reader")
}

或者你用反射reflect也可以

好的大佬,這個是斷言,我也會,感覺go中啥都不難,就是介面這一塊快把我逼瘋了,看來我要把標準檔案看一遍了,前輩,你可以跟我說一下你作業中經常用到的介面嗎?我先看這些吧,要不然盲目的看沒個頭啊,

uj5u.com熱心網友回復:

參考 8 樓 與蘤舊縐的回復:
沒懟過標準庫,不清楚這個
但有一點很簡單,你可能在某處宣告了一個介面,然后因為洋文水平有限,編不出太多方法的名字,于是反復使用某幾個名字,導致不知不覺間很多結構體都實作了那個介面
但這并不是一個問題,你的介面并不在乎有多少個結構體實作了它,你的結構體也并不在乎不知不覺間多實作了幾個介面,只需要最初的那幾對,也就是你有意實作的那幾個實作了就行
標準庫是人家寫的,人家把實作藏哪了你翻半天找不到很正常,何必管它,你又不清楚人家的分層、模式、邏輯,既然能賦值,那就是實作了
但有一點很重要,如果跨包實作介面,包丟了怎么辦,你可能哪天覺得專案哪個部分不要了,重寫,結果另外一個包內的騷操作就報錯了,這并不是說不能跨包,而是在架構設計上應當避免的問題,確保他們在一個整體中,要死一起死,要活一起活

多謝大佬,那個您可以提供一下您作業中常用到的幾個介面嗎?我要先把這幾個介面看一下了。

uj5u.com熱心網友回復:

你要給一個介面變數賦值,就必須實作介面定義的所有方法,空介面因為沒有定義任何方法,所以可以認為任何東西都實作了空介面,任何都可以給空介面賦值。你把sort.Sort官方檔案的例子看一下,變會明白了。

package sort_test
import (
    "fmt"
    "sort"
)
// A Change is a record of source code changes, recording user, language, and delta size.
type Change struct {
    user     string
    language string
    lines    int
}
type lessFunc func(p1, p2 *Change) bool
// multiSorter implements the Sort interface, sorting the changes within.
type multiSorter struct {
    changes []Change
    less    []lessFunc
}
// Sort sorts the argument slice according to the less functions passed to OrderedBy.
func (ms *multiSorter) Sort(changes []Change) {
    ms.changes = changes
    sort.Sort(ms)
}
// OrderedBy returns a Sorter that sorts using the less functions, in order.
// Call its Sort method to sort the data.
func OrderedBy(less ...lessFunc) *multiSorter {
    return &multiSorter{
        less: less,
    }
}
// Len is part of sort.Interface.
func (ms *multiSorter) Len() int {
    return len(ms.changes)
}
// Swap is part of sort.Interface.
func (ms *multiSorter) Swap(i, j int) {
    ms.changes[i], ms.changes[j] = ms.changes[j], ms.changes[i]
}
// Less is part of sort.Interface. It is implemented by looping along the
// less functions until it finds a comparison that is either Less or
// !Less. Note that it can call the less functions twice per call. We
// could change the functions to return -1, 0, 1 and reduce the
// number of calls for greater efficiency: an exercise for the reader.
func (ms *multiSorter) Less(i, j int) bool {
    p, q := &ms.changes[i], &ms.changes[j]
    // Try all but the last comparison.
    var k int
    for k = 0; k < len(ms.less)-1; k++ {
        less := ms.less[k]
        switch {
        case less(p, q):
            // p < q, so we have a decision.
            return true
        case less(q, p):
            // p > q, so we have a decision.
            return false
        }
        // p == q; try the next comparison.
    }
    // All comparisons to here said "equal", so just return whatever
    // the final comparison reports.
    return ms.less[k](p, q)
}
var changes = []Change{
    {"gri", "Go", 100},
    {"ken", "C", 150},
    {"glenda", "Go", 200},
    {"rsc", "Go", 200},
    {"r", "Go", 100},
    {"ken", "Go", 200},
    {"dmr", "C", 100},
    {"r", "C", 150},
    {"gri", "Smalltalk", 80},
}
// ExampleMultiKeys demonstrates a technique for sorting a struct type using different
// sets of multiple fields in the comparison. We chain together "Less" functions, each of
// which compares a single field.
func Example_sortMultiKeys() {
    // Closures that order the Change structure.
    user := func(c1, c2 *Change) bool {
        return c1.user < c2.user
    }
    language := func(c1, c2 *Change) bool {
        return c1.language < c2.language
    }
    increasingLines := func(c1, c2 *Change) bool {
        return c1.lines < c2.lines
    }
    decreasingLines := func(c1, c2 *Change) bool {
        return c1.lines > c2.lines // Note: > orders downwards.
    }
    // Simple use: Sort by user.
    OrderedBy(user).Sort(changes)
    fmt.Println("By user:", changes)
    // More examples.
    OrderedBy(user, increasingLines).Sort(changes)
    fmt.Println("By user,<lines:", changes)
    OrderedBy(user, decreasingLines).Sort(changes)
    fmt.Println("By user,>lines:", changes)
    OrderedBy(language, increasingLines).Sort(changes)
    fmt.Println("By language,<lines:", changes)
    OrderedBy(language, increasingLines, user).Sort(changes)
    fmt.Println("By language,<lines,user:", changes)
    // Output:
    // By user: [{dmr C 100} {glenda Go 200} {gri Smalltalk 80} {gri Go 100} {ken Go 200} {ken C 150} {r Go 100} {r C 150} {rsc Go 200}]
    // By user,<lines: [{dmr C 100} {glenda Go 200} {gri Smalltalk 80} {gri Go 100} {ken C 150} {ken Go 200} {r Go 100} {r C 150} {rsc Go 200}]
    // By user,>lines: [{dmr C 100} {glenda Go 200} {gri Go 100} {gri Smalltalk 80} {ken Go 200} {ken C 150} {r C 150} {r Go 100} {rsc Go 200}]
    // By language,<lines: [{dmr C 100} {ken C 150} {r C 150} {gri Go 100} {r Go 100} {ken Go 200} {glenda Go 200} {rsc Go 200} {gri Smalltalk 80}]
    // By language,<lines,user: [{dmr C 100} {ken C 150} {r C 150} {gri Go 100} {r Go 100} {glenda Go 200} {ken Go 200} {rsc Go 200} {gri Smalltalk 80}]
}


其中 sort.Sort(data Interface),Sort方法接收的是一個介面型別,定義有Sort包里
type Interface interface {
// Len is the number of elements in the collection.
Len() int
// Less reports whether the element with
// index i should sort before the element with index j.
Less(i, j int) bool
// Swap swaps the elements with indexes i and j.
Swap(i, j int)
}

你看到了吧,代碼里傳的 sort.Sort(ms),這個ms就必須實作Len() int,Less(i,j int)bool,Swap(i,j int)這3個方法,ms才能傳進去不報錯,你洗掉一個方法試試,馬上報錯。

go 里的介面實作是非注入性的,(不需要在實作介面的類里指明繼承哪個介面)相比java,.net里的介面,耦合性小,找的話,你開發工具用JetBrains GoLand,,結構體multiSorter左邊有上I+向上紅色箭頭的,你點擊一下,該結構體實作所有的介面都會列出來,你可以查看任何一個介面的定義,當然,只有multiSorter實作在介面才會有這個紅色箭頭出現。

uj5u.com熱心網友回復:

開發工具不要用vscode,我沒發現vscode里可以快速查找介面的,而且vscode里代碼量一大,連代碼提示彈出來都很慢,怎么設配置都沒有用,不是一般的難用。

uj5u.com熱心網友回復:

參考 12 樓 ying1234的回復:
你要給一個介面變數賦值,就必須實作介面定義的所有方法,空介面因為沒有定義任何方法,所以可以認為任何東西都實作了空介面,任何都可以給空介面賦值。你把sort.Sort官方檔案的例子看一下,變會明白了。

package sort_test
import (
    "fmt"
    "sort"
)
// A Change is a record of source code changes, recording user, language, and delta size.
type Change struct {
    user     string
    language string
    lines    int
}
type lessFunc func(p1, p2 *Change) bool
// multiSorter implements the Sort interface, sorting the changes within.
type multiSorter struct {
    changes []Change
    less    []lessFunc
}
// Sort sorts the argument slice according to the less functions passed to OrderedBy.
func (ms *multiSorter) Sort(changes []Change) {
    ms.changes = changes
    sort.Sort(ms)
}
// OrderedBy returns a Sorter that sorts using the less functions, in order.
// Call its Sort method to sort the data.
func OrderedBy(less ...lessFunc) *multiSorter {
    return &multiSorter{
        less: less,
    }
}
// Len is part of sort.Interface.
func (ms *multiSorter) Len() int {
    return len(ms.changes)
}
// Swap is part of sort.Interface.
func (ms *multiSorter) Swap(i, j int) {
    ms.changes[i], ms.changes[j] = ms.changes[j], ms.changes[i]
}
// Less is part of sort.Interface. It is implemented by looping along the
// less functions until it finds a comparison that is either Less or
// !Less. Note that it can call the less functions twice per call. We
// could change the functions to return -1, 0, 1 and reduce the
// number of calls for greater efficiency: an exercise for the reader.
func (ms *multiSorter) Less(i, j int) bool {
    p, q := &ms.changes[i], &ms.changes[j]
    // Try all but the last comparison.
    var k int
    for k = 0; k < len(ms.less)-1; k++ {
        less := ms.less[k]
        switch {
        case less(p, q):
            // p < q, so we have a decision.
            return true
        case less(q, p):
            // p > q, so we have a decision.
            return false
        }
        // p == q; try the next comparison.
    }
    // All comparisons to here said "equal", so just return whatever
    // the final comparison reports.
    return ms.less[k](p, q)
}
var changes = []Change{
    {"gri", "Go", 100},
    {"ken", "C", 150},
    {"glenda", "Go", 200},
    {"rsc", "Go", 200},
    {"r", "Go", 100},
    {"ken", "Go", 200},
    {"dmr", "C", 100},
    {"r", "C", 150},
    {"gri", "Smalltalk", 80},
}
// ExampleMultiKeys demonstrates a technique for sorting a struct type using different
// sets of multiple fields in the comparison. We chain together "Less" functions, each of
// which compares a single field.
func Example_sortMultiKeys() {
    // Closures that order the Change structure.
    user := func(c1, c2 *Change) bool {
        return c1.user < c2.user
    }
    language := func(c1, c2 *Change) bool {
        return c1.language < c2.language
    }
    increasingLines := func(c1, c2 *Change) bool {
        return c1.lines < c2.lines
    }
    decreasingLines := func(c1, c2 *Change) bool {
        return c1.lines > c2.lines // Note: > orders downwards.
    }
    // Simple use: Sort by user.
    OrderedBy(user).Sort(changes)
    fmt.Println("By user:", changes)
    // More examples.
    OrderedBy(user, increasingLines).Sort(changes)
    fmt.Println("By user,<lines:", changes)
    OrderedBy(user, decreasingLines).Sort(changes)
    fmt.Println("By user,>lines:", changes)
    OrderedBy(language, increasingLines).Sort(changes)
    fmt.Println("By language,<lines:", changes)
    OrderedBy(language, increasingLines, user).Sort(changes)
    fmt.Println("By language,<lines,user:", changes)
    // Output:
    // By user: [{dmr C 100} {glenda Go 200} {gri Smalltalk 80} {gri Go 100} {ken Go 200} {ken C 150} {r Go 100} {r C 150} {rsc Go 200}]
    // By user,<lines: [{dmr C 100} {glenda Go 200} {gri Smalltalk 80} {gri Go 100} {ken C 150} {ken Go 200} {r Go 100} {r C 150} {rsc Go 200}]
    // By user,>lines: [{dmr C 100} {glenda Go 200} {gri Go 100} {gri Smalltalk 80} {ken Go 200} {ken C 150} {r C 150} {r Go 100} {rsc Go 200}]
    // By language,<lines: [{dmr C 100} {ken C 150} {r C 150} {gri Go 100} {r Go 100} {ken Go 200} {glenda Go 200} {rsc Go 200} {gri Smalltalk 80}]
    // By language,<lines,user: [{dmr C 100} {ken C 150} {r C 150} {gri Go 100} {r Go 100} {glenda Go 200} {ken Go 200} {rsc Go 200} {gri Smalltalk 80}]
}


其中 sort.Sort(data Interface),Sort方法接收的是一個介面型別,定義有Sort包里
type Interface interface {
// Len is the number of elements in the collection.
Len() int
// Less reports whether the element with
// index i should sort before the element with index j.
Less(i, j int) bool
// Swap swaps the elements with indexes i and j.
Swap(i, j int)
}

你看到了吧,代碼里傳的 sort.Sort(ms),這個ms就必須實作Len() int,Less(i,j int)bool,Swap(i,j int)這3個方法,ms才能傳進去不報錯,你洗掉一個方法試試,馬上報錯。

go 里的介面實作是非注入性的,(不需要在實作介面的類里指明繼承哪個介面)相比java,.net里的介面,耦合性小,找的話,你開發工具用JetBrains GoLand,,結構體multiSorter左邊有上I+向上紅色箭頭的,你點擊一下,該結構體實作所有的介面都會列出來,你可以查看任何一個介面的定義,當然,只有multiSorter實作在介面才會有這個紅色箭頭出現。

好的,多謝大佬,另外想問一下,goland好破解嗎?

uj5u.com熱心網友回復:

網上有破解版的,我裝的是JetBrains GoLand 2019.2.3 ,百度搜一下好多破解,有老版本的先卸載,有效期到2089年,足夠用了。

uj5u.com熱心網友回復:

參考 15 樓 ying1234的回復:
網上有破解版的,我裝的是JetBrains GoLand 2019.2.3 ,百度搜一下好多破解,有老版本的先卸載,有效期到2089年,足夠用了。

好的,多謝了,前輩,你可以跟我說一下你們作業中經常用的的幾個包和介面嗎?我想重點先看這幾個。

uj5u.com熱心網友回復:

學生可以申請免費,應該是每年驗證一次,不過你這感覺不像是大學生的樣子
必須用學校郵箱注冊,即后綴為edu的郵箱
看原始碼沒有一個好檔案費時費力,介面的操作基本的都在了,剩下怎么神奇大半是架構搭建的功勞
實在想懟原始碼就找個輕量級的
給你推薦幾個,聽別人講的好像還挺常用的
日志:github.com/sirupsen/logrus
web(公司內部使用):github.com/gin-gonic/gin
資料庫:github.com/go-sql-driver/mysql、github.com/jinzhu/gorm(這個太肥了)

uj5u.com熱心網友回復:

話說還有一個看起來挺好玩的github.com/PuerkitoBio/goquery
go語言版的jQuery

uj5u.com熱心網友回復:

參考 17 樓 與蘤舊縐的回復:
學生可以申請免費,應該是每年驗證一次,不過你這感覺不像是大學生的樣子
必須用學校郵箱注冊,即后綴為edu的郵箱
看原始碼沒有一個好檔案費時費力,介面的操作基本的都在了,剩下怎么神奇大半是架構搭建的功勞
實在想懟原始碼就找個輕量級的
給你推薦幾個,聽別人講的好像還挺常用的
日志:github.com/sirupsen/logrus
web(公司內部使用):github.com/gin-gonic/gin
資料庫:github.com/go-sql-driver/mysql、github.com/jinzhu/gorm(這個太肥了)

真的太感謝您了,您可能不知道對于我這種一個人摸爬滾打自學編程的人來說,你們這些有經驗的人士的指導和建議都是對我有著非常大的幫助,身邊沒有會編程的人,老師也沒有會的,遇到不會的題只能百度(百度也有好多解決不了的問題),加了好幾個go的學習群問別人題了人家直接給我發個百度的鏈接,真的很無奈,在這里發帖子能得到您們這些專業人士的回答,真的很有動力,感謝。

uj5u.com熱心網友回復:

參考 18 樓 與蘤舊縐的回復:
話說還有一個看起來挺好玩的github.com/PuerkitoBio/goquery
go語言版的jQuery

這些資料我都會好好看的,

uj5u.com熱心網友回復:

大家都是單干的,互幫互助吧

uj5u.com熱心網友回復:

參考 22 樓 與蘤舊縐的回復:
大家都是單干的,互幫互助吧

嗯嗯,單干太難了,希望有朝一日今天的努力不會白費。

uj5u.com熱心網友回復:

參考 16 樓 CSDN首席執行官 的回復:
Quote: 參考 15 樓 ying1234的回復:
網上有破解版的,我裝的是JetBrains GoLand 2019.2.3 ,百度搜一下好多破解,有老版本的先卸載,有效期到2089年,足夠用了。

好的,多謝了,前輩,你可以跟我說一下你們作業中經常用的的幾個包和介面嗎?我想重點先看這幾個。
你看看go官方中文檔案吧,常用的包無非就是fmt,net/http,net,sync,io,os,encoding/xml,encoding/json,time,encoding,zip,strings,reflect等等,象map,struct,slice,array之些資料結構,還有重點就是go 多協程chan之類

uj5u.com熱心網友回復:

db操作也是基本啊,別外的github里多找找開源的吧。

uj5u.com熱心網友回復:

參考 25 樓 ying1234的回復:
db操作也是基本啊,別外的github里多找找開源的吧。

好的,非常感謝大佬的指教。

uj5u.com熱心網友回復:

厲害大佬就是牛呢

uj5u.com熱心網友回復:

http介面需要特別處理么?區別就是http屬于不穩定連接,需要錯誤處理代碼。

uj5u.com熱心網友回復:

參考 28 樓 luj_1768的回復:
http介面需要特別處理么?區別就是http屬于不穩定連接,需要錯誤處理代碼。

http包還不了解,沒深入學習,基礎打好了再學http包

uj5u.com熱心網友回復:

別想那么復雜,本來go設計時就是想避免開發者在一堆介面實作關系中懵逼。go里的介面只是一種規范而已

uj5u.com熱心網友回復:

參考 34 樓 ARong.的回復:
別想那么復雜,本來go設計時就是想避免開發者在一堆介面實作關系中懵逼。go里的介面只是一種規范而已

主要我怕介面沒搞明明白白之后學新的包容易懵逼比如net包

uj5u.com熱心網友回復:

go中介面這個隱式實作,有些物件實作了哪個介面根本不知道,所以也不敢亂賦值,這一塊有點暈,比如Writer介面,根本不知道有多少物件實作了這個介面,所以也不敢傳引數。

uj5u.com熱心網友回復:

參考 34 樓 ARong.的回復:
別想那么復雜,本來go設計時就是想避免開發者在一堆介面實作關系中懵逼。go里的介面只是一種規范而已

go中介面這個隱式實作,有些物件實作了哪個介面根本不知道,所以也不敢亂賦值,這一塊有點暈,比如Writer介面,根本不知道有多少物件實作了這個介面,所以也不敢傳引數。

uj5u.com熱心網友回復:

人工置頂

檔案它不香的嗎

順便吐槽一句,某些作者同志更新框架都不同步更新檔案的說

uj5u.com熱心網友回復:

參考 39 樓 與蘤舊縐的回復:
人工置頂

檔案它不香的嗎

順便吐槽一句,某些作者同志更新框架都不同步更新檔案的說

檔案感覺看的不是太明白。

uj5u.com熱心網友回復:

檔案全英文,遍地都是坑,英語得學好,坑還得自個兒填,天天面向github編程

uj5u.com熱心網友回復:

參考 41 樓 與蘤舊縐的回復:
檔案全英文,遍地都是坑,英語得學好,坑還得自個兒填,天天面向github編程

是啊,現在我也在嘗試學習使用github,感覺這個很有用。

uj5u.com熱心網友回復:

參考 5 樓 CSDN首席執行官的回復:
Quote: 參考 1 樓 qybao的回復:
介面是一種“規范”,也就是介面的實作類都要遵循這個“規范”,假如這個“規范”體現在介面的方法上,那么所有的介面實作類都要實作該介面方法(遵循“規范”,和介面一致,即介面有什么動作,實作類也有什么動作)。那么好了,如果有一個類,它封裝的方法恰好和介面定義的方法一致,也就是說它無形中遵循了介面的“規范”,所以它隱形的成了介面的實作類

打個比方,某工廠的一批零件有個生產指標,比如直徑為10cm(可以理解為有個介面方法),那么在這個工廠里生產的零件都符合這個指標,也就是都符合這個介面,因為在該工廠生產的,所以顯示地遵循了標準(也就是顯示實作介面)。那么好了,另一家工廠也生產一種零件,剛好直徑也是10cm(可以理解為有個方法和介面方法一樣)。假如我么第一家工廠生產的零件壞了,我們要找一個零件代替,我們發現另一家工廠的零件剛好也是10cm(也有同樣的介面方法),也符合第一家工廠的生產指標,所以也可以拿來代替使用。你會發現,另一家工廠沒有特意去遵循第一個工廠的指標(沒有顯示implement),但事實上卻隱式的遵循的指標,也就是說另一家工廠的零件,隱式地實作了第一家工廠的介面,所以它也和第一家工廠生產的零件一樣,能應用在相同的場合。

謝謝大佬,我自己定義的介面和結構體之間的使用我還是能搞明白的,(介面的規則我懂了)但是標準庫里邊的我就有點搞不懂了,比如
Readall( io reader)
Readall方法接收一個實作了io reader介面的引數,但是下邊的例子file怎么就變成就實作io reader介面的引數了?os. Open后回傳的應該是os. Open型別的變數,我怎么知道和確定file實作了io reader介面?講真的,我是真的看不出來file這個變數能跟io reader介面有半毛錢關系,大佬拜托您指點。

func main() { 
file, _ := os.Open("test")
 b, _ := ioutil.ReadAll(file) 
 fmt.Println(string(b)) 
}

雖然沒學過golang  但是標準庫是人家寫的,回傳什么人家決定的。這個是需要記的。reader介面也只是file結構體的方法集合,提前寫好的一些方法,也可以用自己的結構體來繼承這些方法。在rust中管這些叫trait

uj5u.com熱心網友回復:

參考 43 樓 wuxingren888的回復:
Quote: 參考 5 樓 CSDN首席執行官的回復:
Quote: 參考 1 樓 qybao的回復:
介面是一種“規范”,也就是介面的實作類都要遵循這個“規范”,假如這個“規范”體現在介面的方法上,那么所有的介面實作類都要實作該介面方法(遵循“規范”,和介面一致,即介面有什么動作,實作類也有什么動作)。那么好了,如果有一個類,它封裝的方法恰好和介面定義的方法一致,也就是說它無形中遵循了介面的“規范”,所以它隱形的成了介面的實作類

打個比方,某工廠的一批零件有個生產指標,比如直徑為10cm(可以理解為有個介面方法),那么在這個工廠里生產的零件都符合這個指標,也就是都符合這個介面,因為在該工廠生產的,所以顯示地遵循了標準(也就是顯示實作介面)。那么好了,另一家工廠也生產一種零件,剛好直徑也是10cm(可以理解為有個方法和介面方法一樣)。假如我么第一家工廠生產的零件壞了,我們要找一個零件代替,我們發現另一家工廠的零件剛好也是10cm(也有同樣的介面方法),也符合第一家工廠的生產指標,所以也可以拿來代替使用。你會發現,另一家工廠沒有特意去遵循第一個工廠的指標(沒有顯示implement),但事實上卻隱式的遵循的指標,也就是說另一家工廠的零件,隱式地實作了第一家工廠的介面,所以它也和第一家工廠生產的零件一樣,能應用在相同的場合。

謝謝大佬,我自己定義的介面和結構體之間的使用我還是能搞明白的,(介面的規則我懂了)但是標準庫里邊的我就有點搞不懂了,比如
Readall( io reader)
Readall方法接收一個實作了io reader介面的引數,但是下邊的例子file怎么就變成就實作io reader介面的引數了?os. Open后回傳的應該是os. Open型別的變數,我怎么知道和確定file實作了io reader介面?講真的,我是真的看不出來file這個變數能跟io reader介面有半毛錢關系,大佬拜托您指點。

func main() { 
file, _ := os.Open("test")
 b, _ := ioutil.ReadAll(file) 
 fmt.Println(string(b)) 
}

雖然沒學過golang  但是標準庫是人家寫的,回傳什么人家決定的。這個是需要記的。reader介面也只是file結構體的方法集合,提前寫好的一些方法,也可以用自己的結構體來繼承這些方法。在rust中管這些叫trait

好的 , 多謝大佬指教

uj5u.com熱心網友回復:

參考 43 樓 wuxingren888的回復:
Quote: 參考 5 樓 CSDN首席執行官的回復:
Quote: 參考 1 樓 qybao的回復:
介面是一種“規范”,也就是介面的實作類都要遵循這個“規范”,假如這個“規范”體現在介面的方法上,那么所有的介面實作類都要實作該介面方法(遵循“規范”,和介面一致,即介面有什么動作,實作類也有什么動作)。那么好了,如果有一個類,它封裝的方法恰好和介面定義的方法一致,也就是說它無形中遵循了介面的“規范”,所以它隱形的成了介面的實作類

打個比方,某工廠的一批零件有個生產指標,比如直徑為10cm(可以理解為有個介面方法),那么在這個工廠里生產的零件都符合這個指標,也就是都符合這個介面,因為在該工廠生產的,所以顯示地遵循了標準(也就是顯示實作介面)。那么好了,另一家工廠也生產一種零件,剛好直徑也是10cm(可以理解為有個方法和介面方法一樣)。假如我么第一家工廠生產的零件壞了,我們要找一個零件代替,我們發現另一家工廠的零件剛好也是10cm(也有同樣的介面方法),也符合第一家工廠的生產指標,所以也可以拿來代替使用。你會發現,另一家工廠沒有特意去遵循第一個工廠的指標(沒有顯示implement),但事實上卻隱式的遵循的指標,也就是說另一家工廠的零件,隱式地實作了第一家工廠的介面,所以它也和第一家工廠生產的零件一樣,能應用在相同的場合。

謝謝大佬,我自己定義的介面和結構體之間的使用我還是能搞明白的,(介面的規則我懂了)但是標準庫里邊的我就有點搞不懂了,比如
Readall( io reader)
Readall方法接收一個實作了io reader介面的引數,但是下邊的例子file怎么就變成就實作io reader介面的引數了?os. Open后回傳的應該是os. Open型別的變數,我怎么知道和確定file實作了io reader介面?講真的,我是真的看不出來file這個變數能跟io reader介面有半毛錢關系,大佬拜托您指點。

func main() { 
file, _ := os.Open("test")
 b, _ := ioutil.ReadAll(file) 
 fmt.Println(string(b)) 
}

雖然沒學過golang  但是標準庫是人家寫的,回傳什么人家決定的。這個是需要記的。reader介面也只是file結構體的方法集合,提前寫好的一些方法,也可以用自己的結構體來繼承這些方法。在rust中管這些叫trait

好的 , 多謝大佬指教

轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/110745.html

標籤:go語言

上一篇:求助!!哪位大神會在R里調整系統發育進化樹的分支長度啊?

下一篇:求解pycharm Process finished with exit code 0

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 網閘典型架構簡述

    網閘架構一般分為兩種:三主機的三系統架構網閘和雙主機的2+1架構網閘。 三主機架構分別為內端機、外端機和仲裁機。三機無論從軟體和硬體上均各自獨立。首先從硬體上來看,三機都用各自獨立的主板、記憶體及存盤設備。從軟體上來看,三機有各自獨立的作業系統。這樣能達到完全的三機獨立。對于“2+1”系統,“2”分為 ......

    uj5u.com 2020-09-10 02:00:44 more
  • 如何從xshell上傳檔案到centos linux虛擬機里

    如何從xshell上傳檔案到centos linux虛擬機里及:虛擬機CentOs下執行 yum -y install lrzsz命令,出現錯誤:鏡像無法找到軟體包 前言 一、安裝lrzsz步驟 二、上傳檔案 三、遇到的問題及解決方案 總結 前言 提示:其實很簡單,往虛擬機上安裝一個上傳檔案的工具 ......

    uj5u.com 2020-09-10 02:00:47 more
  • 一、SQLMAP入門

    一、SQLMAP入門 1、判斷是否存在注入 sqlmap.py -u 網址/id=1 id=1不可缺少。當注入點后面的引數大于兩個時。需要加雙引號, sqlmap.py -u "網址/id=1&uid=1" 2、判斷文本中的請求是否存在注入 從文本中加載http請求,SQLMAP可以從一個文本檔案中 ......

    uj5u.com 2020-09-10 02:00:50 more
  • Metasploit 簡單使用教程

    metasploit 簡單使用教程 浩先生, 2020-08-28 16:18:25 分類專欄: kail 網路安全 linux 文章標簽: linux資訊安全 編輯 著作權 metasploit 使用教程 前言 一、Metasploit是什么? 二、準備作業 三、具體步驟 前言 Msfconsole ......

    uj5u.com 2020-09-10 02:00:53 more
  • 游戲逆向之驅動層與用戶層通訊

    驅動層代碼: #pragma once #include <ntifs.h> #define add_code CTL_CODE(FILE_DEVICE_UNKNOWN,0x800,METHOD_BUFFERED,FILE_ANY_ACCESS) /* 更多游戲逆向視頻www.yxfzedu.com ......

    uj5u.com 2020-09-10 02:00:56 more
  • 北斗電力時鐘(北斗授時服務器)讓網路資料更精準

    北斗電力時鐘(北斗授時服務器)讓網路資料更精準 北斗電力時鐘(北斗授時服務器)讓網路資料更精準 京準電子科技官微——ahjzsz 近幾年,資訊技術的得了快速發展,互聯網在逐漸普及,其在人們生活和生產中都得到了廣泛應用,并且取得了不錯的應用效果。計算機網路資訊在電力系統中的應用,一方面使電力系統的運行 ......

    uj5u.com 2020-09-10 02:01:03 more
  • 【CTF】CTFHub 技能樹 彩蛋 writeup

    ?碎碎念 CTFHub:https://www.ctfhub.com/ 筆者入門CTF時時剛開始刷的是bugku的舊平臺,后來才有了CTFHub。 感覺不論是網頁UI設計,還是題目質量,賽事跟蹤,工具軟體都做得很不錯。 而且因為獨到的金幣制度的確讓人有一種想去刷題賺金幣的感覺。 個人還是非常喜歡這個 ......

    uj5u.com 2020-09-10 02:04:05 more
  • 02windows基礎操作

    我學到了一下幾點 Windows系統目錄結構與滲透的作用 常見Windows的服務詳解 Windows埠詳解 常用的Windows注冊表詳解 hacker DOS命令詳解(net user / type /md /rd/ dir /cd /net use copy、批處理 等) 利用dos命令制作 ......

    uj5u.com 2020-09-10 02:04:18 more
  • 03.Linux基礎操作

    我學到了以下幾點 01Linux系統介紹02系統安裝,密碼啊破解03Linux常用命令04LAMP 01LINUX windows: win03 8 12 16 19 配置不繁瑣 Linux:redhat,centos(紅帽社區版),Ubuntu server,suse unix:金融機構,證券,銀 ......

    uj5u.com 2020-09-10 02:04:30 more
  • 05HTML

    01HTML介紹 02頭部標簽講解03基礎標簽講解04表單標簽講解 HTML前段語言 js1.了解代碼2.根據代碼 懂得挖掘漏洞 (POST注入/XSS漏洞上傳)3.黑帽seo 白帽seo 客戶網站被黑帽植入劫持代碼如何處理4.熟悉html表單 <html><head><title>TDK標題,描述 ......

    uj5u.com 2020-09-10 02:04:36 more
最新发布
  • 2023年最新微信小程式抓包教程

    01 開門見山 隔一個月發一篇文章,不過分。 首先回顧一下《微信系結手機號資料庫被脫庫事件》,我也是第一時間得知了這個訊息,然后跟蹤了整件事情的經過。下面是這起事件的相關截圖以及近日流出的一萬條資料樣本: 個人認為這件事也沒什么,還不如關注一下之前45億快遞資料查詢渠道疑似在近日復活的訊息。 訊息是 ......

    uj5u.com 2023-04-20 08:48:24 more
  • web3 產品介紹:metamask 錢包 使用最多的瀏覽器插件錢包

    Metamask錢包是一種基于區塊鏈技術的數字貨幣錢包,它允許用戶在安全、便捷的環境下管理自己的加密資產。Metamask錢包是以太坊生態系統中最流行的錢包之一,它具有易于使用、安全性高和功能強大等優點。 本文將詳細介紹Metamask錢包的功能和使用方法。 一、 Metamask錢包的功能 數字資 ......

    uj5u.com 2023-04-20 08:47:46 more
  • vulnhub_Earth

    前言 靶機地址->>>vulnhub_Earth 攻擊機ip:192.168.20.121 靶機ip:192.168.20.122 參考文章 https://www.cnblogs.com/Jing-X/archive/2022/04/03/16097695.html https://www.cnb ......

    uj5u.com 2023-04-20 07:46:20 more
  • 從4k到42k,軟體測驗工程師的漲薪史,給我看哭了

    清明節一過,盲猜大家已經無心上班,在數著日子準備過五一,但一想到銀行卡里的余額……瞬間心情就不美麗了。最近,2023年高校畢業生就業調查顯示,本科畢業月平均起薪為5825元。調查一出,便有很多同學表示自己又被平均了。看著這一資料,不免讓人想到前不久中國青年報的一項調查:近六成大學生認為畢業10年內會 ......

    uj5u.com 2023-04-20 07:44:00 more
  • 最新版本 Stable Diffusion 開源 AI 繪畫工具之中文自動提詞篇

    🎈 標簽生成器 由于輸入正向提示詞 prompt 和反向提示詞 negative prompt 都是使用英文,所以對學習母語的我們非常不友好 使用網址:https://tinygeeker.github.io/p/ai-prompt-generator 這個網址是為了讓大家在使用 AI 繪畫的時候 ......

    uj5u.com 2023-04-20 07:43:36 more
  • 漫談前端自動化測驗演進之路及測驗工具分析

    隨著前端技術的不斷發展和應用程式的日益復雜,前端自動化測驗也在不斷演進。隨著 Web 應用程式變得越來越復雜,自動化測驗的需求也越來越高。如今,自動化測驗已經成為 Web 應用程式開發程序中不可或缺的一部分,它們可以幫助開發人員更快地發現和修復錯誤,提高應用程式的性能和可靠性。 ......

    uj5u.com 2023-04-20 07:43:16 more
  • CANN開發實踐:4個DVPP記憶體問題的典型案例解讀

    摘要:由于DVPP媒體資料處理功能對存放輸入、輸出資料的記憶體有更高的要求(例如,記憶體首地址128位元組對齊),因此需呼叫專用的記憶體申請介面,那么本期就分享幾個關于DVPP記憶體問題的典型案例,并給出原因分析及解決方法。 本文分享自華為云社區《FAQ_DVPP記憶體問題案例》,作者:昇騰CANN。 DVPP ......

    uj5u.com 2023-04-20 07:43:03 more
  • msf學習

    msf學習 以kali自帶的msf為例 一、msf核心模塊與功能 msf模塊都放在/usr/share/metasploit-framework/modules目錄下 1、auxiliary 輔助模塊,輔助滲透(埠掃描、登錄密碼爆破、漏洞驗證等) 2、encoders 編碼器模塊,主要包含各種編碼 ......

    uj5u.com 2023-04-20 07:42:59 more
  • Halcon軟體安裝與界面簡介

    1. 下載Halcon17版本到到本地 2. 雙擊安裝包后 3. 步驟如下 1.2 Halcon軟體安裝 界面分為四大塊 1. Halcon的五個助手 1) 影像采集助手:與相機連接,設定相機引數,采集影像 2) 標定助手:九點標定或是其它的標定,生成標定檔案及內參外參,可以將像素單位轉換為長度單位 ......

    uj5u.com 2023-04-20 07:42:17 more
  • 在MacOS下使用Unity3D開發游戲

    第一次發博客,先發一下我的游戲開發環境吧。 去年2月份買了一臺MacBookPro2021 M1pro(以下簡稱mbp),這一年來一直在用mbp開發游戲。我大致分享一下我的開發工具以及使用體驗。 1、Unity 官網鏈接: https://unity.cn/releases 我一般使用的Apple ......

    uj5u.com 2023-04-20 07:40:19 more