Go學習筆記3

来源:https://www.cnblogs.com/Gao-yubo/archive/2023/09/07/17686389.html
-Advertisement-
Play Games

隨著金融科技的發展,越來越多的人選擇線上銀行或移動銀行上進行日常交易。在進行這些交易之前,通常需要進行身份驗證以確保賬戶的安全性。其中,銀行卡二要素驗證是一種常見的身份驗證方式。本文將為大家介紹如何使用銀行卡二要素驗證API介面,具體實現方法如下。 一、API介面介紹 銀行卡二要素驗證API介面是一 ...


九、錯誤處理

1.defer+recover機制處理異常錯誤

展示錯誤:

image-20230907111853394

發現:程式中出現錯誤/恐慌以後,程式被中斷,無法繼續執行。

錯誤處理/捕獲機制:

內置函數recover:

image-20230907111929849 image-20230907111939200

2.自定義錯誤

需要調用errors包下的New函數:函數返回error類型

image-20230907112050176 image-20230907112101527

3.panic

有一種情況:程式出現錯誤以後,後續代碼就沒有必要執行,想讓程式中斷,退出程式:
藉助:builtin包下內置函數:panic

image-20230907112123210 image-20230907112131779

十、數組

1.使用

數組定義格式:
var 數組名 [數組大小]數據類型
例如:

var scores [5]int
package main
import "fmt"
func main(){
        //實現的功能:給出五個學生的成績,求出成績的總和,平均數:
        //給出五個學生的成績:--->數組存儲:
        //定義一個數組:
        var scores [5]int
        //將成績存入數組:
        scores[0] = 95
        scores[1] = 91
        scores[2] = 39
        scores[3] = 60
        scores[4] = 21
        //求和:
        //定義一個變數專門接收成績的和:
        sum := 0
        for i := 0;i < len(scores);i++ {//i: 0,1,2,3,4 
                sum += scores[i]
        }
        //平均數:
        avg := sum / len(scores)
        //輸出
        fmt.Printf("成績的總和為:%v,成績的平均數為:%v",sum,avg)
}

2.記憶體分析

賦值記憶體(數組是值類型,在棧中開闢記憶體)

image-20230907114627864

3.數組的遍歷

【1】普通for迴圈
【2】鍵值迴圈
(鍵值迴圈) for range結構是Go語言特有的一種的迭代結構,在許多情況下都非常有用,for range 可以遍曆數組、切片、字元串、map 及通道,for range 語法上類似於其它語言中的 foreach 語句,一般形式為:

for key, val := range coll {
    ...
}

註意:
(1)coll就是你要的數組
(2)每次遍歷得到的索引用key接收,每次遍歷得到的索引位置上的值用val
(3)key、value的名字隨便起名 k、v key、value
(4)key、value屬於在這個迴圈中的局部變數
(5)你想忽略某個值:用_就可以了:

image-20230907114756788
package main
import "fmt"
func main(){
        //實現的功能:給出五個學生的成績,求出成績的總和,平均數:
        //給出五個學生的成績:--->數組存儲:
        //定義一個數組:
        var scores [5]int
        //將成績存入數組:(迴圈 + 終端輸入)
        for i := 0; i < len(scores);i++ {//i:數組的下標
                fmt.Printf("請錄入第個%d學生的成績",i + 1)
                fmt.Scanln(&scores[i])
        }
        //展示一下班級的每個學生的成績:(數組進行遍歷)
        //方式1:普通for迴圈:
        for i := 0; i < len(scores);i++ {
                fmt.Printf("第%d個學生的成績為:%d\n",i+1,scores[i])
        }
        fmt.Println("-------------------------------")
        //方式2:for-range迴圈
        for key,value := range scores {
                fmt.Printf("第%d個學生的成績為:%d\n",key + 1,value)
        }
}

結果:

image-20230907114916858

4.數組的初始化操作

package main
import "fmt"
func main(){
        //第一種:
        var arr1 [3]int = [3]int{3,6,9}
        fmt.Println(arr1)
        //第二種:
        var arr2 = [3]int{1,4,7}
        fmt.Println(arr2)
        //第三種:
        var arr3 = [...]int{4,5,6,7}
        fmt.Println(arr3)
        //第四種:
        var arr4 = [...]int{2:66,0:33,1:99,3:88}
        fmt.Println(arr4)
}

5.註意事項

【1】長度屬於類型的一部分 :

image-20230907114958806

【2】Go中數組屬值類型,在預設情況下是值傳遞,因此會進行值拷貝。

image-20230907115006602

【3】如想在其它函數中,去修改原來的數組,可以使用引用傳遞(指針方式)。

image-20230907115012762

6.二維數組

二維數組有初始值,

image-20230907170553154

初始化:

image-20230907170712976

遍歷

package main
import "fmt"
func main(){
        //定義二維數組:
        var arr [3][3]int = [3][3]int{{1,4,7},{2,5,8},{3,6,9}}
        fmt.Println(arr)
        fmt.Println("------------------------")
        //方式1:普通for迴圈:
        for i := 0;i < len(arr);i++{
                for j := 0;j < len(arr[i]);j++ {
                        fmt.Print(arr[i][j],"\t")
                }
                fmt.Println()
        }
        fmt.Println("------------------------")
        //方式2:for range迴圈:
        for key,value := range arr {
                for k,v := range value {
                        fmt.Printf("arr[%v][%v]=%v\t",key,k,v)
                }
                fmt.Println()
        }
}

十一、切片

【1】切片(slice)是golang中一種特有的數據類型

【2】數組有特定的用處,但是卻有一些呆板(數組長度固定不可變),所以在 Go 語言的代碼里並不是特別常見。相對的切片卻是隨處可見的,切片是一種建立在數組類型之上的抽象,它構建在數組之上並且提供更強大的能力和便捷。

【3】切片(slice)是對數組一個連續片段的引用,所以切片是一個引用類型。這個片段可以是整個數組,或者是由起始和終止索引標識的一些項的子集。需要註意的是,終止索引標識的項不包括在切片內。切片提供了一個相關數組的動態視窗。

1.語法

var 切片名 []類型 = 數組的一個片段引用
image-20230907213036099

2.記憶體分析

切片有3個欄位的數據結構:一個是指向底層數組的指針,一個是切片的長度,一個是切片的容量。

image-20230907213225615

3.定義

【1】方式1:定義一個切片,然後讓切片去引用一個已經創建好的數組。

image-20230907213250992

【2】方式2:通過make內置函數來創建切片。基本語法: var切片名[type = make([], len,[cap])

image-20230907213257916

make底層創建一個數組,對外不可見,所以不可以直接操作這個數組,要通過slice去間接的訪問各個元素,不可以直接對數組進行維護/操作
【3】方式3:定一個切片,直接就指定具體數組,使用原理類似make的方式。

image-20230907213306357

4.遍歷

【1】方式1:for迴圈常規方式遍歷
【2】方式2:for-range 結構遍歷切片

package main
import "fmt"
func main(){
        //定義切片:
        slice := make([]int,4,20)
        slice[0] = 66
        slice[1] = 88
        slice[2] = 99
        slice[3] = 100
        //方式1:普通for迴圈
        for i := 0;i < len(slice);i++ {
                fmt.Printf("slice[%v] = %v \t" ,i,slice[i])
        }
        fmt.Println("\n------------------------------")
        //方式2:for-range迴圈:
        for i,v := range slice {
                fmt.Printf("下標:%v ,元素:%v\n" ,i,v)
        }
}

5.註意事項

【1】切片定義後不可以直接使用,需要讓其引用到一個數組,或者make一個空間供切片來使用

image-20230907213432846

【2】切片使用不能越界。

image-20230907213437814

【3】簡寫方式:

  1. var slice = arr[0:end] ----》 var slice = arr[:end]
  2. var slice = arr[start:len(arr)] ----》 var slice = arr[start:]
  3. var slice = arr[0:len(arr)] ----》 var slice = arr[:]

【4】切片可以繼續切片

image-20230907213444333

【5】切片可以動態增長

package main
import "fmt"
func main(){
        //定義數組:
        var intarr [6]int = [6]int{1,4,7,3,6,9}
        //定義切片:
        var slice []int = intarr[1:4] //4,7,3
        fmt.Println(len(slice))
        slice2 := append(slice,88,50)
        fmt.Println(slice2) //[4 7 3 88 50]
        fmt.Println(slice)
        //底層原理:
        //1.底層追加元素的時候對數組進行擴容,老數組擴容為新數組:
        //2.創建一個新數組,將老數組中的4,7,3複製到新數組中,在新數組中追加88,50
        //3.slice2 底層數組的指向 指向的是新數組 
        //4.往往我們在使用追加的時候其實想要做的效果給slice追加:
        slice = append(slice,88,50)
        fmt.Println(slice)
        //5.底層的新數組 不能直接維護,需要通過切片間接維護操作。
}

可以通過append函數將切片追加給切片:

image-20230907213450635

【6】切片的拷貝:

package main
import "fmt"
func main(){
        //定義切片:
        var a []int = []int{1,4,7,3,6,9}
        //再定義一個切片:
        var b []int = make([]int,10)
        //拷貝:
        copy(b,a) //將a中對應數組中元素內容複製到b中對應的數組中
        fmt.Println(b)
}

十二、映射

1.map的引入

【1】映射(map), Go語言中內置的一種類型,它將鍵值對相關聯,我們可以通過鍵 key來獲取對應的值 value。 類似其它語言的集合

image-20230907213531160

【2】基本語法

var map變數名 map[keytype]valuetype

key、value的類型:bool、數字、string、指針、channel 、還可以是只包含前面幾個類型的介面、結構體、數組
key通常為int 、string類型,value通常為數字(整數、浮點數)、string、map、結構體
key:slice、map、function不可以

【3】代碼:
map的特點:
(1)map集合在使用前一定要make
(2)map的key-value是無序的
(3)key是不可以重覆的,如果遇到重覆,後一個value會替換前一個value
(4)value可以重覆的

package main
import "fmt"
func main(){
        //定義map變數:
        var a map[int]string
        //只聲明map記憶體是沒有分配空間
        //必須通過make函數進行初始化,才會分配空間:
        a = make(map[int]string,10) //map可以存放10個鍵值對
        //將鍵值對存入map中:
        a[20095452] = "張三"
        a[20095387] = "李四"
        a[20097291] = "王五"
        a[20095387] = "朱六"
        a[20096699] = "張三"
        //輸出集合
        fmt.Println(a)
}

2.創建

package main
import "fmt"
func main(){
        //方式1:
        //定義map變數:
        var a map[int]string
        //只聲明map記憶體是沒有分配空間
        //必須通過make函數進行初始化,才會分配空間:
        a = make(map[int]string,10) //map可以存放10個鍵值對
        //將鍵值對存入map中:
        a[20095452] = "張三"
        a[20095387] = "李四"
        //輸出集合
        fmt.Println(a)
        //方式2:
        b := make(map[int]string)
        b[20095452] = "張三"
        b[20095387] = "李四"
        fmt.Println(b)
        //方式3:
        c := map[int]string{
                20095452 : "張三",
                20098765 : "李四",
        }
        c[20095387] = "王五"
        fmt.Println(c)
}

3.操作

1】增加和更新操作:
map["key"]= value ——》 如果key還沒有,就是增加,如果key存在就是修改。
【2】刪除操作:
delete(map,"key") , delete是一個內置函數,如果key存在,就刪除該key-value,如果k的y不存在,不操作,但是也不會報錯

image-20230907213729406

【3】清空操作:
(1)如果我們要刪除map的所有key ,沒有一個專門的方法一次刪除,可以遍歷一下key,逐個刪除
(2)或者map = make(...),make一個新的,讓原來的成為垃圾,被gc回收
【4】查找操作:
value ,bool = map[key]
value為返回的value,bool為是否返回 ,要麼true 要麼false

package main
import "fmt"
func main(){
        //定義map
        b := make(map[int]string)
        //增加:
        b[20095452] = "張三"
        b[20095387] = "李四"
        //修改:
        b[20095452] = "王五"
        //刪除:
        delete(b,20095387)
        delete(b,20089546)
        fmt.Println(b)
        //查找:
        value,flag := b[200]
        fmt.Println(value)
        fmt.Println(flag)
}

【5】獲取長度:len函數

【6】遍歷:for-range

package main
import "fmt"
func main(){
        //定義map
        b := make(map[int]string)
        //增加:
        b[20095452] = "張三"
        b[20095387] = "李四"
        b[20098833] = "王五"
        //獲取長度:
        fmt.Println(len(b))
        //遍歷:
        for k,v := range b {
                fmt.Printf("key為:%v value為%v \t",k,v)
        }
        fmt.Println("---------------------------")
        //加深難度:
        a := make(map[string]map[int]string)
        //賦值:
        a["班級1"] = make(map[int]string,3)
        a["班級1"][20096677] = "露露"
        a["班級1"][20098833] = "麗麗"
        a["班級1"][20097722] = "菲菲"
        a["班級2"] = make(map[int]string,3)
        a["班級2"][20089911] = "小明"
        a["班級2"][20085533] = "小龍"
        a["班級2"][20087244] = "小飛"
        for k1,v1:= range a {
                fmt.Println(k1)
                for k2,v2:= range v1{
                        fmt.Printf("學生學號為:%v 學生姓名為%v \t",k2,v2)
                }
                fmt.Println()
        }
}

十三、對象

1.對象的引入

【1】Golang語言面向對象編程說明:
(1)Golang也支持面向對象編程(OOP),但是和傳統的面向對象編程有區別,並不是純粹的面向對象語言。所以我們說Golang支持面向對象編程特性是比較準確的。
(2)Golang沒有類(class),Go語言的結構體(struct)和其它編程語言的類(class)有同等的地位,你可以理解Gelang是基於struct來實現OOP特性的。
(3)Golang面向對象編程非常簡潔,去掉了傳統OOP語言的方法重載、構造函數和析構函數、隱藏的this指針等等
(4)Golang仍然有面向對象編程的繼承,封裝和多態的特性,只是實現的方式和其它OOP語言不一樣,比如繼承:Golang沒有extends 關鍵字,繼承是通過匿名欄位來實現。

【2】結構體的引入:

具體的對象:
一位老師:郜宇博老師: 姓名:郜宇博 年齡:22歲 性別 :男 ......

可以使用變數來處理:

package main
import "fmt"
func main(){
        //郜宇博老師: 姓名:郜宇博   年齡:22歲   性別 :男 ...... 
        var name string = "郜宇博"
        var age int = 22
        var sex string = "男"
        //馬士兵老師:
        var name2 string = "馬士兵"
        var age2 int = 45
        var sex2 string = "男"
       
}

缺點:
(1)不利於數據的管理、維護
(2)老師的很多屬性屬於一個對象,用變數管理太分散了

2.結構體

代碼:

package main
import "fmt"
//定義老師結構體,將老師中的各個屬性  統一放入結構體中管理:
type Teacher struct{
        //變數名字大寫外界可以訪問這個屬性
        Name string
        Age int
        School string
}
func main(){
        //創建老師結構體的實例、對象、變數:
        var t1 Teacher // var a int
        fmt.Println(t1) //在未賦值時預設值:{ 0 }
        t1.Name = "馬士兵"
        t1.Age = 45
        t1.School = "清華大學"
        fmt.Println(t1)
        fmt.Println(t1.Age + 10)
}

3.結構體的創建

1.直接創建

image-20230907214202449

2.附帶初始值

image-20230907214222933

3.結構體指針創建

image-20230907214243724 image-20230907214249171

4.結構體之間轉換

【1】結構體是用戶單獨定義的類型,和其它類型進行轉換時需要有完全相同的欄位(名字、個數和類型)

package main
import "fmt"
type Student struct {
        Age int
}
type Person struct {
        Age int
}
func main(){
        var s Student = Student{10}
        var p Person = Person{10}
        s = Student(p)
        fmt.Println(s)
        fmt.Println(p)
}

【2】結構體進行type重新定義(相當於取別名),Golang認為是新的數據類型,但是相互間可以強轉

package main
import "fmt"
type Student struct {
        Age int
}
type Stu Student
func main(){
        var s1 Student = Student{19}
        var s2 Stu = Stu{19}
        s1 = Student(s2)
        fmt.Println(s1)
        fmt.Println(s2)
}

5.方法的引入

【1】方法是作用在指定的數據類型上、和指定的數據類型綁定,因此自定義類型,都可以有方法,而不僅僅是struct
【2】方法的聲明和調用格式:
聲明:

type A struct {
                Num int
}
func (a A) test() {
                fmt.Println(a.Num)
}

調用:

var a A
a.test()

(1)func (a A) test()相當於A結構體有一個方法叫test
(2)(a A)體現方法test和結構體A綁定關係

(3)代碼層面:

image-20230907233032350

註意:
(1)test方法中參數名字隨意起
(2)結構體Person和test方法綁定,調用test方法必須靠指定的類型:Person
(3)如果其他類型變數調用test方法一定會報錯。
(4)結構體對象傳入test方法中,值傳遞,和函數參數傳遞一致。

image-20230907233044542

6.方法的註意事項

(1)結構體類型是值類型,在方法調用中,遵守值類型的傳遞機制,是值拷貝傳遞方式

image-20230907233118300

(2)如程式員希望在方法中,改變結構體變數的值,可以通過結構體指針的方式來處理

image-20230907233123227 image-20230907233131792

我們寫程式的時候,可以直接簡化:

image-20230907233136349

底層編譯器做了優化,底層會自動幫我們加上 & *

(3)Golang中的方法作用在指定的數據類型上的,和指定的數據類型綁定,因此自定義類型,都可以有方法,而不僅僅是struct,比如int , float32等都可以有方法

package main
import "fmt"
type integer int
func (i integer) print(){
        i = 30
        fmt.Println("i = ",i)
}
func (i *integer) change(){
        *i = 30
        fmt.Println("i = ",*i)
}
func main(){
        var i integer = 20
        i.print()
        i.change()
        fmt.Println(i)
}

(4)方法的訪問範圍控制的規則,和函數一樣。方法名首字母小寫,只能在本包訪問,方法首字母大寫,可以在本包和其它包訪問。

(5)如果一個類型實現了String()這個方法,那麼fmt.Println預設會調用這個變數的String()進行輸出

以後定義結構體的話,常定義String()作為輸出結構體信息的方法,在fmt.Println會自動調用

package main
import "fmt"
type Student struct{
        Name string
        Age int
}
func (s *Student) String() string{
        str := fmt.Sprintf("Name = %v , Age = %v",s.Name,s.Age)
        return str
}
func main(){
        stu := Student{
                Name : "麗麗",
                Age : 20,
        }
        //傳入地址,如果綁定了String方法就會自動調用
        fmt.Println(&stu)
}

7.方法和函數的區別

【1】綁定指定類型:
方法:需要綁定指定數據類型
函數:不需要綁定數據類型

【2】調用方式不一樣:
函數的調用方式:
函數名(實參列表)
方法的調用方式:變數.方法名(實參列表)

package main
import "fmt"
type Student struct{
        Name string
}
//定義方法:
func (s Student) test01(){
        fmt.Println(s.Name)
}
//定義函數:
func method01(s Student){
        fmt.Println(s.Name)
}
func main(){
        //調用函數:
        var s Student = Student{"麗麗"}
        method01(s)
        //方法調用:
        s.test01()
}

【3】對於函數來說,參數類型對應是什麼就要傳入什麼。

package main
import "fmt"
type Student struct{
        Name string
}
//定義函數:
func method01(s Student){
        fmt.Println(s.Name)
}
func method02(s *Student){
        fmt.Println((*s).Name)
}
func main(){
        var s Student = Student{"麗麗"}
        method01(s)
        //method01(&s)錯誤
        method02(&s)
        //method02(s)錯誤
}

【4】對於方法來說,接收者為值類型,可以傳入指針類型,接受者為指針類型,可以傳入值類型。

package main
import "fmt"
type Student struct{
        Name string
}
//定義方法:
func (s Student) test01(){
        fmt.Println(s.Name)
}
func (s *Student) test02(){
        fmt.Println((*s).Name)
}
func main(){
        var s Student = Student{"麗麗"}
        s.test01()
        (&s).test01()//雖然用指針類型調用,但是傳遞還是按照值傳遞的形式
        (&s).test02()
        s.test02()//等價
}

8.創建結構體時初始化

【1】方式1:按照順序賦值操作
缺點:必須按照順序有局限性
【2】方式2:按照指定類型
【3】方式3:想要返回結構體的指針類型

image-20230907233304075
您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 原文地址:https://www.mssqltips.com/sqlservertip/3598/troubleshooting-transactional-replication-latency-issues-in-sql-server/ 問題 我安裝了幾個SQL Server 2012實例的集群 ...
  • sidebar: auto # Android 調試橋 (adb) Android 調試橋 (adb) 是一種功能多樣的命令行工具,可讓您與設備進行通信。adb 命令可用於執行各種設備操作,例如安裝和調試應用。adb 提供對 Unix shell(可用來在設備上運行各種命令)的訪問許可權。它是一種客戶 ...
  • 在Service中使用系統dialog彈框,但是無法覆蓋全部,底部菜單依然可以被點擊,在某些場景下是不符合需求的 getDialog().getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ERROR); 顯然是 dialog 的層級 ...
  • # 什麼是Promise (含如何判斷一個值是Promise) > 本文旨在對 Promise 的規範進行解釋, 便於讀者在學習 Promise 的過程中梳理 Promise 之間的操作關係, 不對具體的代碼實現和Promise用法進行解釋. > > 比如, 為什麼 [[MDN-await]](ht ...
  • 寫在前面:初次嘗試小程式,在不使用框架的情況下,如果遇到問題,可以儘量去參考官方文檔 1.scroll-view組件 scroll-view是一個可滑動的組塊.需要設置其中具體的height高度,並且在標簽中設置scroll-y="true"; 1 <scroll-view class="sceol ...
  • 一、小程式代碼構成 1.創建文件 在app.json文件中,pages中,直接寫上要添加的文件的名及路徑,然後保存即可(此方法在Mac上親測沒成功), Mac創建頁面的方式: pages文件右鍵,新建文件,然後輸入文件名 ![](https://img2023.cnblogs.com/blog/29 ...
  • 本文給大家介紹了什麼是"編程範式",選擇合適的編程範式可以提高代碼的可讀性、可維護性和可擴展性。 一、 什麼是編程範式? "編程範式"是一種編程思想的總稱,它是指在編寫程式時所採用的基本方法和規範。常見的編程範式有面向對象、函數式、邏輯式等。 選擇合適的編程範式可以提高代碼的可讀性、可維護性和可擴展 ...
  • ### 歡迎訪問我的GitHub > 這裡分類和彙總了欣宸的全部原創(含配套源碼):[https://github.com/zq2599/blog_demos](https://github.com/zq2599/blog_demos) ### 關於《LeetCode買賣股票》系列 - 在LeetC ...
一周排行
    -Advertisement-
    Play Games
  • 示例項目結構 在 Visual Studio 中創建一個 WinForms 應用程式後,項目結構如下所示: MyWinFormsApp/ │ ├───Properties/ │ └───Settings.settings │ ├───bin/ │ ├───Debug/ │ └───Release/ ...
  • [STAThread] 特性用於需要與 COM 組件交互的應用程式,尤其是依賴單線程模型(如 Windows Forms 應用程式)的組件。在 STA 模式下,線程擁有自己的消息迴圈,這對於處理用戶界面和某些 COM 組件是必要的。 [STAThread] static void Main(stri ...
  • 在WinForm中使用全局異常捕獲處理 在WinForm應用程式中,全局異常捕獲是確保程式穩定性的關鍵。通過在Program類的Main方法中設置全局異常處理,可以有效地捕獲並處理未預見的異常,從而避免程式崩潰。 註冊全局異常事件 [STAThread] static void Main() { / ...
  • 前言 給大家推薦一款開源的 Winform 控制項庫,可以幫助我們開發更加美觀、漂亮的 WinForm 界面。 項目介紹 SunnyUI.NET 是一個基於 .NET Framework 4.0+、.NET 6、.NET 7 和 .NET 8 的 WinForm 開源控制項庫,同時也提供了工具類庫、擴展 ...
  • 說明 該文章是屬於OverallAuth2.0系列文章,每周更新一篇該系列文章(從0到1完成系統開發)。 該系統文章,我會儘量說的非常詳細,做到不管新手、老手都能看懂。 說明:OverallAuth2.0 是一個簡單、易懂、功能強大的許可權+可視化流程管理系統。 有興趣的朋友,請關註我吧(*^▽^*) ...
  • 一、下載安裝 1.下載git 必須先下載並安裝git,再TortoiseGit下載安裝 git安裝參考教程:https://blog.csdn.net/mukes/article/details/115693833 2.TortoiseGit下載與安裝 TortoiseGit,Git客戶端,32/6 ...
  • 前言 在項目開發過程中,理解數據結構和演算法如同掌握蓋房子的秘訣。演算法不僅能幫助我們編寫高效、優質的代碼,還能解決項目中遇到的各種難題。 給大家推薦一個支持C#的開源免費、新手友好的數據結構與演算法入門教程:Hello演算法。 項目介紹 《Hello Algo》是一本開源免費、新手友好的數據結構與演算法入門 ...
  • 1.生成單個Proto.bat內容 @rem Copyright 2016, Google Inc. @rem All rights reserved. @rem @rem Redistribution and use in source and binary forms, with or with ...
  • 一:背景 1. 講故事 前段時間有位朋友找到我,說他的窗體程式在客戶這邊出現了卡死,讓我幫忙看下怎麼回事?dump也生成了,既然有dump了那就上 windbg 分析吧。 二:WinDbg 分析 1. 為什麼會卡死 窗體程式的卡死,入口門檻很低,後續往下分析就不一定了,不管怎麼說先用 !clrsta ...
  • 前言 人工智慧時代,人臉識別技術已成為安全驗證、身份識別和用戶交互的關鍵工具。 給大家推薦一款.NET 開源提供了強大的人臉識別 API,工具不僅易於集成,還具備高效處理能力。 本文將介紹一款如何利用這些API,為我們的項目添加智能識別的亮點。 項目介紹 GitHub 上擁有 1.2k 星標的 C# ...