• Day_03


    1.指针基本操作

    package main
    
    import "fmt"
    
    func main() {
    	var a int
    	//每个变量有2层含义:变量的内存,变量的地址
    	fmt.Printf("a = %d
    ", a)   //变量的内存内容
    	fmt.Printf("&a = %v
    ", &a) //变量的内存地址(指针)
    
    	//保存某个变量的地址,需要指针类型	*int  保存int的地址,	**int保存*int的地址
    	//声明(定义),定义只是特殊的声明
    	//定义一个变量p,类型为*int
    	var p *int
    	p = &a //指针变量指向谁,就把谁的地址赋值给指针变量
    	fmt.Printf("p = %v,&a = %v
    ", p, &a)
    
    	*p = 666 //*p操作的不是p的内存,是p所指向的内存(就是a)
    	fmt.Printf("*p = %v,a = %v
    ", *p, a)
    }
    

     2.不要操作没有合法指向的内存

    package main
    
    import "fmt"
    
    func main() {
    	var p *int
    	p = nil
    	fmt.Println("p = ", p)
    
    	//*p = 666	//err,因为p没有合法指向
    
    	var a int
    	p = &a //p指向a
    	*p = 666
    	fmt.Println("a = ", a)
    
    }
    

     3.new函数的使用

    package main
    
    import "fmt"
    
    func main() {
    	var p *int
    	p = new(int)
    	*p = 666
    	fmt.Println("*p = ", *p)
    
    	q := new(int) //自动推导类型,更简便
    	*q = 777
    	fmt.Println("*q = ", *q)
    
    }
    
    /*
    总结:其实就是c语言的动态地址分配
    不过c语言需要释放内存地址从而回收空间(GC)
    而Go语言无需担心其内存的生命周期或垃圾回收
    Go语言的内存管理系统会自动处理
    */
    

     4.普通变量做函数参数(值传递)

    package main
    
    import "fmt"
    
    func swap(a, b int) {
    	a, b = b, a
    	fmt.Printf("swap: a = %d,b = %d
    ", a, b)
    }
    
    func main() {
    	a, b := 10, 20
    
    	//通过一个函数交换a和b的内容
    	swap(a, b) //变量本身传递,值传递(站在变量角度)
    	fmt.Printf("main: a = %d,b = %d
    ", a, b)
    }
    
    /*
    输出结果:
    swap: a = 20,b = 10
    main: a = 10,b = 20
    
    */
    

     5.指针做函数参数(地址传递)

    package main
    
    import "fmt"
    
    func swap(p1, p2 *int) {
    	*p1, *p2 = *p2, *p1
    }
    func main() {
    	a, b := 10, 20
    
    	//通过一个函数交换a和b的内容
    	swap(&a, &b) //内存地址传递
    	fmt.Printf("main: a = %d,b = %d
    ", a, b)
    }
    
    /*
    运行结果: main: a = 20,b = 10
    这次交换成功了
    */
    

     6.为什么需要数组

    package main
    
    import "fmt"
    
    func main() {
    
    	//定义一个数组id,内有50个元素,[]内不能用常量
    	var id [50]int
    
    	//操作数组,通过下标,从0开始,到len()-1
    	for i := 0; i < len(id); i++ {
    		id[i] = i + 1
    		fmt.Printf("第一种方式:id[%d] = %d
    ", i, id[i])
    	}
    	//i返回下标,data返回元素
    	for i, data := range id {
    		id[i] = i + 1
    		fmt.Printf("第二种方式:id[%d] = %d
    ", i, data)
    
    	}
    
    }
    

    7.数组的基本使用(同上)

    8.数组的初始化

    package main
    
    import "fmt"
    
    func main() {
    	//声明定义同时赋值,叫初始化
    	//1.全部初始化
    	var a [5]int = [5]int{1, 2, 3, 4, 5}
    	fmt.Println("a = ", a)
    
    	b := [5]int{1, 2, 3, 4, 5}
    	fmt.Println("b = ", b)
    
    	//2.部分初始化,没有初始化的元素,自动赋值为0
    	c := [5]int{1, 2, 3}
    	fmt.Println("c = ", c)
    
    	//3.指定某个元素初始化,2和4代表的是下标
    	d := [5]int{2: 10, 4: 20}
    	fmt.Println("d = ", d)
    
    }
    

     9.二维数组的介绍

    package main
    
    import "fmt"
    
    func main() {
    	//有多少个[]就是多少维
    	//有多少个[]就用多少个循环
    	var a [3][4]int
    
    	k := 0
    	for i := 0; i < 3; i++ {
    		for j := 0; j < 4; j++ {
    			k++
    			a[i][j] = k
    			fmt.Printf("a[%d][%d] = %d, ", i, j, a[i][j])
    		}
    		fmt.Printf("
    ")
    	}
    	fmt.Println("a = ", a)
    
    	//有3个元素,每个元素又是一维数组[4]int,注意这种方式最好不要换行
    	b := [3][4]int{{1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12}}
    	fmt.Println("b = ", b)
    
    	//部分初始化,没有初始化的值为0
    	c := [3][4]int{{1, 2, 3}, {5, 6, 7, 8}, {9, 10}}
    	fmt.Println("c = ", c)
    
    	//部分初始化,没有初始化的值为0
    	d := [3][4]int{{1, 2, 3, 4}, {5, 6, 7, 8}}
    	fmt.Println("d = ", d)
    
    	//指定下标方式的初始化,没有初始化的值为0
    	e := [3][4]int{1: {5, 6, 7, 8}}
    	fmt.Println("e = ", e)
    
    }
    

     10.数组比较和赋值

    package main
    
    import "fmt"
    
    func main() {
    	a := [5]int{1, 2, 3, 4, 5}
    	b := [5]int{1, 2, 3, 4, 5}
    	c := [5]int{1, 2, 3}
    	fmt.Println("a == b", a == b) //返回true
    	fmt.Println("a == c", a == c) //返回false
    
    	//同类型的数组可以赋值
    	var d [5]int
    	d = a
    	fmt.Println("d = ", d)
    
    }
    

     11.随机数的使用

    package main
    
    import "fmt"
    import "math/rand"
    import "time"
    
    func main() {
    	//设置种子,只需要一次
    	//如果种子参数一样,每次运行程序产生的随机数都一样,我们可以调用系统的时间,这样每次就都不一样了
    	rand.Seed(time.Now().UnixNano()) //以当前系统时间作为种子参数
    
    	for i := 0; i < 5; i++ { //产生4次随机数
    		//产生随机数
    		//fmt.Println("rand = ", rand.Int()) 	//随机很大的数
    		fmt.Println("rand = ", rand.Intn(100)) //限制在100以内
    	}
    
    }
    

     12.冒泡排序

    package main
    
    import "fmt"
    import "math/rand"
    import "time"
    
    func main() {
    	//设置种子,只需要一次
    	//如果种子参数一样,每次运行程序产生的随机数都一样,我们可以调用系统的时间,这样每次就都不一样了
    	rand.Seed(time.Now().UnixNano()) //以当前系统时间作为种子参数
    
    	var a [10]int
    	n := len(a)
    
    	for i := 0; i < n; i++ {
    		a[i] = rand.Intn(100) //100以内的随机数
    		fmt.Printf("%d,", a[i])
    	}
    	fmt.Printf("
    ")
    
    	//冒泡排序,挨着的2个元素比较,升序(大于则交换)
    	for i := 0; i < n-1; i++ {
    		for j := 0; j < n-1-i; j++ {
    			if a[j] > a[j+1] {
    				a[j], a[j+1] = a[j+1], a[j]
    			}
    		}
    	}
    	fmt.Printf("
    排序后:
    ")
    	for i := 0; i < n; i++ {
    		fmt.Printf("%d,", a[i])
    	}
    	fmt.Printf("
    ")
    
    }
    

     13.数组做函数参数

    package main
    
    import "fmt"
    
    //数组做函数参数,它是值传递
    //实参数组的每个元素给形参数组拷贝一份
    //形参的数组是实参数组的复制品
    
    func modify(a [5]int) {
    	a[0] = 666
    	fmt.Println("modify a = ", a)
    
    }
    
    func main() {
    	a := [5]int{1, 2, 3, 4, 5} //初始化
    	modify(a)                  //数组传递过去
    	fmt.Println("main: a = ", a)
    
    }
    
    /*
    运行结果:
    modify a =  [666 2 3 4 5]
    main: a =  [1 2 3 4 5]
    */
    

     14.数组指针做函数

    package main
    
    import "fmt"
    
    //p指向实现数组a,它是指向数组,它是数组指针
    //*p代表指针所指向的内存,就是实参a
    func modify(p *[5]int) {
    	(*p)[0] = 666
    	fmt.Println("modify *a = ", *p)
    
    }
    
    func main() {
    	a := [5]int{1, 2, 3, 4, 5} //初始化
    	modify(&a)                 //地址传递
    	fmt.Println("main: a = ", a)
    
    }
    
    /*
    运行结果:
    modify *a =  [666 2 3 4 5]
    main: a =  [666 2 3 4 5]
    */
    

     15.切片的长度和容量

    package main
    
    import "fmt"
    
    func main() {
    	a := []int{1, 2, 3, 4, 5}
    	s := a[0:3:5]
    	fmt.Println("s = ", s)           //s =  [1 2 3]
    	fmt.Println("len(s) = ", len(s)) //长度	len(s) =  3		3-0
    	fmt.Println("cap(s) = ", cap(s)) //容量	cap(s) =  5		5-0
    
    	s = a[1:4:5]
    	fmt.Println("s = ", s)           //s =  [2 3 4]
    	fmt.Println("len(s) = ", len(s)) //长度	len(s) =  3		4-1
    	fmt.Println("cap(s) = ", cap(s)) //容量	cap(s) =  4		5-1
    
    }
    

     16.切片的创建

    package main
    
    import "fmt"
    
    func main() {
    	//自动推导类型,同时初始化
    	s1 := []int{1, 2, 3, 4}
    	fmt.Println("s1 = ", s1)
    
    	//借助make函数,格式 make(切片类型,长度,容量)
    	s2 := make([]int, 5, 10)
    	fmt.Printf("len = %d,cap = %d
    ", len(s2), cap(s2))
    
    	//没指定容量,容量和长度一样
    	s3 := make([]int, 5)
    	fmt.Printf("len = %d,cap = %d
    ", len(s3), cap(s3))
    
    }
    
    func main_bak() {
    	//切片和数组的区别
    	//数组[]里面的长度是固定的一个常量,数组不能修改长度,len和cap永远都是5
    	a := [5]int{}
    	fmt.Printf("len = %d,cap = %d
    ", len(a), cap(a))
    
    	//切片,[]里面为空,或者为...,切片的长度或容量可以不固定
    	s := []int{}
    	fmt.Printf("len = %d,cap = %d
    ", len(s), cap(s))
    
    	s = append(s, 11) //给切片末尾添加一个成员
    	fmt.Printf("len = %d,cap = %d
    ", len(s), cap(s))
    
    }
    

     17.切片的截取

    package main
    
    import "fmt"
    
    func main() {
    	array := []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
    	s1 := array[:] //不指定容量,则容量和长度一样
    	fmt.Println("s1 = ", s1)
    	fmt.Printf("len = %d,cap = %d
    ", len(s1), cap(s1))
    
    	//操作某个元素,和数组操作方式一样
    	data := array[0]
    	fmt.Println("data = ", data)
    
    	s2 := array[3:6:7] //a[3],a[4],a[5]	len = 6-3 =3	cap = 7-3=4
    	fmt.Println("s2 = ", s2)
    	fmt.Printf("len = %d,cap = %d
    ", len(s2), cap(s2))
    
    	s3 := array[:6] //从0开始,6个元素		常用
    	fmt.Println("s3 = ", s3)
    	fmt.Printf("len = %d,cap = %d
    ", len(s3), cap(s3))
    
    	s4 := array[3:] //从下标为3开始,到结尾
    	fmt.Println("s4 = ", s4)
    	fmt.Printf("len = %d,cap = %d
    ", len(s4), cap(s4))
    
    }
    

     18.切片和底层数组的关系

    package main
    
    import "fmt"
    
    func main() {
    	a := []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
    
    	//新切片
    	s1 := a[2:5] //从a[2]开始,取3个元素
    	s1[1] = 666
    	fmt.Println("s1 = ", s1)
    	fmt.Println("a = ", a) //我们发现底层数组也跟着一起改变了
    
    	//另外一个新切片
    	s2 := s1[2:7]
    	s2[2] = 777
    	fmt.Println("s2 = ", s2) //s2 =  [4 5 777 7 8]
    	fmt.Println("a = ", a)   //a =  [0 1 2 666 4 5 777 7 8 9]
    
    }
    

     19.append函数的使用

    package main
    
    
    import "fmt"
    
    
    func main() {
    	s1 := []int{}
    	fmt.Printf("len = %d,cap = %d
    ", len(s1), cap(s1))
    	//在原切片的末尾添加元素
    	s1 = append(s1, 1)
    	s1 = append(s1, 2)
    	s1 = append(s1, 3)
    	fmt.Println("s1 = ", s1)
    	fmt.Printf("len = %d,cap = %d
    ", len(s1), cap(s1))
    }

     20.append扩容特点

    package main
    
    import "fmt"
    
    func main() {
    	//如果超过原来的容量,通常以2倍容量扩容
    	s := make([]int, 0, 1) //容量为1
    	oldCap := cap(s)
    	for i := 0; i < 20; i++ {
    		s = append(s, i)
    		if newCap := cap(s); oldCap < newCap {
    			fmt.Printf("cap: %d=======> %d
    ", oldCap, newCap)
    			oldCap = newCap
    		}
    	}
    }
    

     21.copy的使用

    package main
    
    import "fmt"
    
    func main() {
    	srcSlice := []int{1, 2}
    	dstSlice := []int{6, 6, 6, 6, 6}
    
    	copy(dstSlice, srcSlice)        //把srcSlice的切片拷贝给dstSlice
    	fmt.Println("dst = ", dstSlice) //dst =  [1 2 6 6 6]
    
    }
    

     22.切片做函数参数

    package main
    
    import "fmt"
    import "math/rand"
    import "time"
    
    func InitData(s []int) {
    	//设置种子
    	rand.Seed(time.Now().UnixNano())
    
    	for i := 0; i < len(s); i++ {
    		s[i] = rand.Intn(100) //产生100以内的随机数
    
    	}
    
    }
    
    //冒泡排序
    func BubbleSort(s []int) {
    	n := len(s)
    	for i := 0; i < n-1; i++ {
    		for j := 0; j < n-1-i; j++ {
    			if s[j] > s[j+1] {
    				s[j], s[j+1] = s[j+1], s[j]
    			}
    
    		}
    
    	}
    
    }
    
    func main() {
    	n := 10
    	//创建一个切片,len为n
    	s := make([]int, n)
    
    	InitData(s) //初始化数组
    	fmt.Println("排序前:---->", s)
    
    	BubbleSort(s)
    	fmt.Println("排序后:---->", s)
    }
    
    //总结:数组是值传递,切片是引用传递
    

     23.猜数字游戏

    package main
    
    import "fmt"
    import "math/rand"
    import "time"
    
    func CreateNum(p *int) {
    	//设置种子
    	rand.Seed(time.Now().UnixNano())
    	var num int
    	for {
    		num = rand.Intn(10000) //有可能出现231,22这种数字
    		if num >= 1000 {       //只取4位数
    			break
    		}
    	}
    	//fmt.Println("num = ", num)
    	*p = num
    }
    
    func GetNum(s []int, num int) {
    	s[0] = num / 1000       //取千位
    	s[1] = num % 1000 / 100 //取百位
    	s[2] = num % 100 / 10   //取十位
    	s[3] = num % 10         //取个位
    
    }
    
    func OnGame(randSlice []int) {
    	var num int
    	keySlice := make([]int, 4)
    
    	for {
    		for {
    			fmt.Printf("请输入一个4位数:")
    			fmt.Scan(&num)
    
    			//999 <= num < 10000
    			if 999 < num && num <= 10000 {
    				break
    			}
    			fmt.Println("输入的数不符合要求")
    		}
    		fmt.Println("num = ", num)
    
    		GetNum(keySlice, num)
    		//fmt.Println("keySlice = ", keySlice)
    
    		n := 0
    		for i := 0; i < 4; i++ {
    			if keySlice[i] > randSlice[i] {
    				fmt.Printf("第%d位大了一点
    ", i+1)
    			} else if keySlice[i] < randSlice[i] {
    				fmt.Printf("第%d位小了一点
    ", i+1)
    			} else {
    				fmt.Printf("第%d位猜对了
    ", i+1)
    				n++
    			}
    
    		}
    		if n == 4 { //4位都猜对了
    			fmt.Println("全部猜对!!!")
    			break //跳出循环
    
    		}
    
    	}
    }
    
    func main() {
    	var randNum int
    	//产生一个4位的随机数
    	CreateNum(&randNum)
    	//fmt.Println("randNum = ", randNum)
    
    	randSlice := make([]int, 4)
    	//保存这个4位数的每一位,利用除法依次除以1000、100、10取商、取余的方式,这里我们将其定义为一个函数
    	GetNum(randSlice, randNum)
    	//fmt.Println("randSlice = ", randSlice)
    
    	/*
    		n1 := 1234 / 1000			//取商
    		n2 := 1234 %1000 / 100 		//取余数,结果为234,  234/100取商得到2
    		fmt.Println("n1 = ",n1)
    		fmt.Println("n2 = ",n2)
    	*/
    	OnGame(randSlice) //游戏函数
    
    }
    

     24.Map的基本使用

    package main
    
    import "fmt"
    
    func main() {
    	//定义一个变量,类型为map[int]string,就是python里面的字典类型
    	var m1 map[int]string
    	fmt.Println("m1 = ", m1)
    	//对于map只有len,没有cap
    	fmt.Println("len(m1) = ", len(m1))
    
    	//可以通过make创建,可以指定长度,只是指定了容量,但是里面却是1个数据也没有
    	//指定了长度为2,但是会自动扩容,键值必须唯一
    	m2 := make(map[int]string, 2)
    	m2[1] = "mike"
    	m2[2] = "go"
    	m2[3] = "c++"
    	fmt.Println("m2 = ", m2)
    	fmt.Println("len(m2) = ", len(m2))
    
    	//初始化
    	m3 := map[int]string{1: "mike", 2: "go", 3: "java"}
    	fmt.Println("m3 = ", m3)
    
    }
    

     25.Map赋值

    package main
    
    import "fmt"
    
    func main() {
    	m1 := map[int]string{1: "rooney", 2: "yoyo"}
    	//赋值,如果已经存在的key值,修改内容
    	m1[1] = "Ramos"
    	fmt.Println("m1 = ", m1)
    	m1[3] = "Messi" //追加,map底层自动扩容,和append类似
    	fmt.Println("m1 = ", m1)
    }
    

     26.Map遍历

    package main
    
    import "fmt"
    
    func main() {
    	m := map[int]string{1: "rooney", 2: "yoyo", 3: "go"}
    	//第一个返回值为key,第二个返回值为value,遍历结果是无序的
    	for key, value := range m {
    		fmt.Printf("%d ===========>%s
    ", key, value)
    	}
    
    	//如何判断一个key值是否存在
    	//第一个返回值为key值所对应的value,第二个返回值为key是否存在的条件,
    	//存在ok为true
    	value, ok := m[1]
    	if ok == true {
    		fmt.Println("m[1] = ", value)
    	} else {
    		fmt.Println("key不存在")
    	}
    
    }
    

     27.Map删除

    package main
    
    import "fmt"
    
    func main() {
    	m := map[int]string{1: "rooney", 2: "yoyo", 3: "go"}
    	fmt.Println("m = ", m)
    
    	delete(m, 1) //删除key为1的内容
    	fmt.Println("m = ", m)
    
    }
    

     28.Map做函数参数

    package main
    
    import "fmt"
    
    func test(m map[int]string) {
    	delete(m, 1)
    }
    
    func main() {
    	m := map[int]string{1: "mike", 2: "yoyo", 3: "go"}
    	fmt.Println("m = ", m)
    	test(m) //在函数内部删除某个key
    	fmt.Println("m = ", m)
    
    }
    

     29.结构体普通变量初始化

    package main
    
    import "fmt"
    
    //定义一个结构体类型
    type Student struct {
    	id   int
    	name string
    	sex  byte //字符类型
    	age  int
    	addr string
    }
    
    func main() {
    	//顺序初始化,每个成员都必须初始化,字符类型的会以ascii码来打印
    	var s1 Student = Student{1, "mike", 'm', 18, "sz"}
    	fmt.Println("s1 = ", s1)
    
    	//指定成员初始化,没有初始化的成员自动赋值为0
    	s2 := Student{name: "mike", addr: "bj"}
    	fmt.Println("s1 = ", s2)
    
    }
    

     30.结构体指针变量初始化

    package main
    
    import "fmt"
    
    //定义一个结构体类型
    type Student struct {
    	id   int
    	name string
    	sex  byte //字符类型
    	age  int
    	addr string
    }
    
    func main() {
    	//这次初始化就变成了指针形式了,		&取地址,*代表指针
    	var p1 *Student = &Student{1, "mike", 'm', 18, "sz"}
    	fmt.Println("*p1 = ", *p1) //这里也可以不加*,go会自动识别
    
    	p2 := &Student{name: "mike", addr: "bj"}
    	fmt.Printf("p2 type is %T
    ", p2)
    	fmt.Println("*p2 = ", *p2)
    
    }
    

     31.结构体成员的使用:普通变量

    package main
    
    import "fmt"
    
    //定义一个结构体类型
    type Student struct {
    	id   int
    	name string
    	sex  byte //字符类型
    	age  int
    	addr string
    }
    
    func main() {
    	//定义一个结构体普通变量
    	var s Student
    
    	//操作成员,需要使用点(.)运算符
    	s.id = 1
    	s.name = "mike"
    	s.sex = 'm' //字符
    	s.age = 19
    	s.addr = "sz"
    	fmt.Println("s = ", s)
    
    }
    

     32.结构体成员的使用:指针变量

    package main
    
    import "fmt"
    
    //定义一个结构体类型
    type Student struct {
    	id   int
    	name string
    	sex  byte //字符类型
    	age  int
    	addr string
    }
    
    func main() {
    	//1.指针有合法指向后,才操作成员
    	//先定义一个普通结构体变量
    	var s Student
    	//再定义一个指针变量,保存s的地址
    	var p1 *Student
    	p1 = &s
    
    	//通过指针操作成员   p1.id 和(*p1).id完全等价,只能使用.运算符
    	p1.id = 18
    	(*p1).name = "mike"
    	p1.sex = 'm'
    	p1.age = 19
    	p1.addr = "bj"
    	fmt.Println("p1 = ", p1)
    
    	//2.通过new申请一个结构体
    	p2 := new(Student)
    	p2.id = 25
    	(*p2).name = "Rooney"
    	p2.sex = 'f'
    	p2.age = 27
    	p2.addr = "sz"
    	fmt.Println("p2 = ", p2)
    
    }
    

     33.结构体比较和赋值

    package main
    
    import "fmt"
    
    //定义一个结构体类型
    type Student struct {
    	id   int
    	name string
    	sex  byte //字符类型
    	age  int
    	addr string
    }
    
    func main() {
    	s1 := Student{1, "mike", 'm', 18, "bj"}
    	s2 := Student{1, "mike", 'm', 18, "bj"}
    	s3 := Student{2, "mike", 'm', 18, "bj"}
    	fmt.Println("s1 == s2", s1 == s2)
    	fmt.Println("s1 == s3", s1 == s3)
    
    	//同类型的2个结构体变量可以相互赋值
    	var tmp Student
    	tmp = s3
    	fmt.Println("tmp = ", tmp)
    
    }
    

     34.结构体做为函数参数

    package main
    
    import "fmt"
    
    //定义一个结构体类型
    type Student struct {
    	id   int
    	name string
    	sex  byte //字符类型
    	age  int
    	addr string
    }
    
    func test01(s Student) {
    	s.id = 666
    	fmt.Println("test01: ", s)
    }
    
    func test02(p *Student) {
    	p.id = 888999
    	fmt.Println("test02: ", *p)
    
    }
    
    func main() {
    	s := Student{1, "mike", 'm', 18, "sz"}
    	test01(s) //值传递,形参无法改实参
    	fmt.Println("main(test01): ", s)
    	test02(&s) //地址传递,形参可以改实参
    	fmt.Println("main(test02): ", s)
    }
    

     35.可见性

    如果想使用别的包的函数、结构体、结构体成员
      函数名、类型名、结构体成员变量名、首字母必须大写,可见
      如果首字母是小写,只能在同一个包里使用
    
  • 相关阅读:
    vector tips
    DataTable DataRow String Tips...
    Virtual Key Codes
    有关多线程的一些技术问题
    用异步的方式调用同步方法
    C#线程锁(下)
    C#线程锁(中)
    Web应用中并发控制的实现
    主题:数据库事务与并发(Hibernate)
    前端开发桌面终极工具(FastStone Capture)推荐(转)
  • 原文地址:https://www.cnblogs.com/steven9898/p/11436605.html
Copyright © 2020-2023  润新知