• golang学习总结


    学习golang注意点:

    1. 导的包必须使用;或者使用_未使用的包,作用是调用该包下的初始化方法。
    2. 局部变量声明必须使用。
    3. go语言的包和java的相似,包名.变量访问

    1. 初识go语言

    1.1 Hello World

    package main
    
    import "fmt"
    
    func main() {
    	fmt.Println("hello world");
    }
    

    1.2 go 数据类型

    布尔:

    var a bool = true
    var b bool = false
    

    整型:

    整型分为有符号和无符号的类型

    8, 16 ,32 分别代表位数

    int : 根据系统决定是32位还64位

    int8 : 1个字节,-128~127 相当于java中的short;

    int16 : 2个字节,-215 ~ 215 -1

    int32 : 4个字节 -231 ~231 - 1

    int64: 8个字节-263 ~263 - 1

    uint : .....

    无符号整形都是取值0~216 - 1

    var a int = -3
    var b uint = 3 //uint类型不可以为负数
    

    浮点型:

    var a float32 = 100.0
    var b float64 = 100.00 //默认
    

    字符类型

    golang中的字符使用的是字节保存的,本质就是一个int32类型

    var a byte = 'a'
    var b byte = 'c'
    fmt.Print(a, "===", b)  //输出的是该字节对应的字节码: 97===99
    fmt.Printf("%c === %c", a, b) // a === c
    

    字符串型:

    var str string = "hello world"
    //多行字符串,不需要使用+来连接多行
    var str2 string = `a 
    		asda asdasdadsadasd `
    

    复数类型:

    complex64 是两个float32组成 complex128两个float64组成

    var a complex64 = 10 + 3i
    var b complex128= 10 + 3i //默认
    

    相关操作

    var v= complex(2 , 3) //构造1个复数, 
    a := real(v) //返回复数实部 2
    b := image(v) 返回复数虚部 3
    

    rune类型:

    // rune is an alias for int32 and is equivalent to int32 in all ways. It is
    // used, by convention, to distinguish character values from integer values.
    
    //int32的别名,几乎在所有方面等同于int32
    //它用来区分字符值和整数值
    type rune = int32
    

    1.3 变量常量

    局部变量:

    属于函数或者方法;声明之后必须使用

    var a = 3;
    var b int = 3;
    c := 3
    

    全局变量

    b := 10 这种全局变量声明是错误的

    全局变量的概念:隶属于,声明之后可以不使用

    var a int
    var (
    	c int
    	d string
    )
    var e = 3
    

    常量

    局部

    const a = 3
    

    全局

    const a int = 10
    const b  = 20
    const (
    	d int = 10
    	e string = "ss"
    	f = 30
    ) 
    

    1.5 字符串相关操作

    golang中string底层是通过byte数组实现的,byte使用utf-8编码标识的Unicode文本,每个汉字占3个字节

    1. 求长度
    func strDemo() {
        fmt.Println(len("hello")) //5
        fmt.Println(len("中")) //3
        fmt.Println(len([]rune("中"))) //1, 正确获取中文字符串长度
    }
    
    1. 字符串遍历
    //对中文无法支持
    func strEach() {
    	str := "hello world"
    	for i := 0; i < len(str); i ++ {
    		//fmt.Print(str[i] ,"	") // 104	101	108	108	111	32	119	111	114	108	100
    		//讲字节编码转为字符串输出
    		fmt.Printf("%c	", str[i]) //h	e	l	l	o	 	w	o	r	l	d
    	}
    }
    
    func strEach() {
    	str := "hello world 中国"
    	for i, s := range str {
             //0	h1	e2	l3	l4	o5	 6	w7	o8	r9	l10	d11	 12	中15	国
            fmt.Print(i, "	", string(s))
    	}
    }
    
    //这个可以正确的输出索引
    func strEachRune() {
    	str := "中国人民"
    	for i, s := range []rune(str) {
    		fmt.Println(i, string(s))
    	}
    }
    
    1. 其他操作
    str := "中国人民, hello world"
    index := strings.Index(str, "国") //存在则 index > -1, 否则 == -1   此时index=-3
    split := strings.Split(str, ",")
    replace := strings.Replace(str, "o", "2", 1) //第三个参数标识替换几个,小于0,则替换所有
    result := strings.EqualFold("中国", "中国2") //不区分大小写
    fmt.Println("中国" == "中国H") //区分大小写, 同strings.Compare()5
    

    1.6 相互转换

    1.6.1 基本数据

    golang基本数据数据之间的转换可使用公:T(i) 进行相互转换

    //数据之间的相互转换
    func transfer() {
    	//
    	var i int = 10
    	var j float64 = 11.30
    	x := float64(i)
    	y := int(j)
    	fmt.Print(x, "	", y) //10	11
    }
    

    1.6.2 string <=> 基本数据类型

    1. 基本类型=>string

    fmt.Sprintf(format string, param interface{})

    func stringTrans() {
    	var i int = 10
    	var flag bool = true
    	int_str := fmt.Sprintf("%d", i)
    	bool_str := fmt.Sprintf("%t", flag)
    	fmt.Println(int_str)
    	fmt.Println(bool_str)
    }
    

    strconv

    func stringStrco() {
    	var i int = 10000
    	var flag bool = true
    	var price float64 = 130.32
    	formatInt := strconv.FormatInt(int64(i), 10) //等价: strconv.Itoa(i)
    	formatBool := strconv.FormatBool(flag)
    	formatFloat := strconv.FormatFloat(price, 'f', 10, 64)
    	fmt.Println(formatInt)
    	fmt.Println(formatBool)
    	fmt.Println(formatFloat)
    }
    
    1. String=>基本数据类型
    func strToBase() {
    	str_flag := "true"
    	str_age := "20"
    	str_price := "20.33"
    	flag, _ := strconv.ParseBool(str_flag)
    	age, _ := strconv.ParseInt(str_age, 10, 64)
    	age_int, _ := strconv.Atoi(str_age)
    	price, _ := strconv.ParseFloat(str_price, 64)
    	fmt.Println(flag)
    	fmt.Println(age)
    	fmt.Println(price)
    	fmt.Println(age_int)
    }
    

    1.6.3 字节数组和字符串

    func byteAndStr() {
    	str := "hello world, 中国"
    	data := []byte(str)
    	s := string(data)
    	fmt.Println(s)
    	fmt.Println(data)
    }
    

    1.7 时间

    1. 获取时间
    func timeOperate() {
    	cur := time.Now()
    	curT := time.Now().Unix() //获取时间戳
    	fmt.Println(cur) //2019-01-30 20:40:16.410689 +0800 CST m=+0.000353772
    	fmt.Println(curT) //1548852137
    }
    
    1. 时间和字符串转换
    func formatTime() {
    	format := time.Now().Format("2006-01-02 15:04:05")
    
    	//时间戳转时间
    	var timestamp int64 = 1548852137
    	unix := time.Unix(timestamp, 0).Format("2006-01-02 15:04:05")
    
    	//字符串转时间
    	formatTimeStr := "2017-04-11 13:33:37"
    	strToTime, _ := time.Parse("2006-01-02 15:04:05", formatTimeStr)
    
    	fmt.Println(format) //2019-01-30 21:00:53
    	fmt.Println(unix)
    	fmt.Println(strToTime) //2017-04-11 13:33:37 +0000 UTC
    }
    

    1.8 复合数据类型

    数组和切片(slice)之间的区别:

    ​ 数组:声明的时候必须指定长度var arr [10]int,值类型,但是在java里面数组是引用类型

    ​ Slice: 长度可变,不需要指定长度,引用类型

    1. 数组

    //数组的声明
    func createArray() {
    	var books [3]string
    	books[0] = "java"
    	books[1] = "python"
    	books[2] = "golang"
    
    	names := [3]string{"lisi", "zhansan", "hand"}
    
    	scores := [...]int{89, 59, 30, 100} //根据后面的内容决定长度
    
    	fmt.Println(books)
    	fmt.Println(names)
    	fmt.Println(scores)
    }
    
    //数组的相关操作
    func operateArray() {
    	//数组长度
    	scores := [...]int{89, 59, 30, 100}
    	fmt.Println(len(scores))
    
    	//数组遍历
    	for i := 0; i < len(scores); i++ {
    		fmt.Print(scores[i], "	")
    	}
    
    	fmt.Println()
    
    	for index, value := range scores {
    		fmt.Print(index, "==", value, "	")
    	}
    }
    

    2. slice

    slice是一个比较复杂的数据结构,也就相当于Java里面集合的概念,是一个可变长的数据

    //最简单的一种声明方式
    func createSlice() {
    	var args []int
    	args = make([]int, 10)
    	args[0] = 1
    	args[1] = 2
    	args[2] = 3
    	args[3] = 4
    	args[4] = 5
    	for index, value := range args {
    		fmt.Println(index, value)
    	}
    }
    

    通过数组定义一个切片

    len 切片长度, 表示当前切片元素的个数

    cap切片容量,表示切片可以容纳切片的个数,如果超出则报错

    func createSlice2() {
    	arrays := [...]int{1, 2, 3, 4, 5}
    	slice := arrays[1:4] //[2 3 4]
    	fmt.Println(len(slice)) //3
    	fmt.Println(cap(slice)) //4
    	slice[1] = 10
        //这里可以解释下图
    	fmt.Println(arrays) //[1 2 10 4 5]
    	fmt.Println(slice) // [2 10 4]
    }
    

    这里容量为什么是4?,如图

    append&copy函数

    当append超出原来容量的时候,会扩展原来的容量为原先的两倍

    //append
    func appendFunc() {
    	slice := make([]int, 2, 4)
    	slice[0] = 1
    	slice[1] = 1
    	slice = append(slice, 2)
    	slice = append(slice, 3)
    	slice = append(slice, 4)
    	fmt.Println(len(slice)) //5
    	fmt.Println(cap(slice)) //8
    }
    
    //copy函数的用法
    func copyFunc() {
    	slice := make([]int, 2, 4)
    	slice2 := make([]int, 2, 4)
    	slice[0] = 1
    	slice[1] = 1
        copy(slice2, slice) //相当于 slice2 := slice[:]
    	fmt.Println(slice2) // [1 1]
    }
    

    3. map

    map 数据结构和java的HashMap类似。

    //创建一个map
    func createMap() {
    	var product map[string]interface{} //声明
    	product = make(map[string]interface{}) //初始化
    	product["id"] = 1
    	product["title"] = "口红"
    	product["price"] = 199.33
    	fmt.Println(product)
    }
    
    //遍历map
    func mapForEach() {
    	var product map[string]interface{} //声明
    	product = make(map[string]interface{}) //初始化
    	product["id"] = 1
    	product["title"] = "口红"
    	product["price"] = 199.33
    	for key, value := range product {
    		fmt.Println(key, value)
    	}
    }
    

    1.9 golang面向对象

    1. 结构体

    go语言中的结构体和Java中的类很相似,包含属性,方法等内容。首字母大写对其他包可见,首字母小写只是对本包可见。

    指针和值类型: 指针类型的方法可以修改属性的值,值类型的不可以修改,

    package main
    
    import "fmt"
    
    func main() {
    	student := &Student{"zhansn", 24}
    	fmt.Println(student.GetName())//zhansn
    	student.SetName("lisi")
    	fmt.Println(student.GetName()) //lisi
    }
    
    //对属性小写可以封装
    type Student struct {
    	name string
    	age int
    }
    
    //定义结构体的方法GetName和SetName
    
    
    func (this Student) GetName() string {
    	return this.name
    }
    
    //这里使用指针可以改变属性的内容
    func (this *Student) SetName(name string) {
    	this.name = name
    }
    

    2. 继承

    在go语言中结构体和结构体没有继承,而是通过组合的方式来获取其他结构体的方法。此时的Student可以使用Person的所有属性和方法,无论是否封装。

    package main
    
    import "fmt"
    
    func main() {
    	student := &Student{}
    	fmt.Println(student.GetName()) // ""
    	student.SetName("lisi")
    	fmt.Println(student.GetName()) //lisi
    }
    
    //对属性小写可以封装
    type Student struct {
    	Person
    }
    type Person struct {
    	name string
    	age int
    }
    
    //定义类型的方法
    func (this Person) GetName() string {
    	return this.name
    }
    
    //这里使用指针可以改变属性的内容
    func (this *Person) SetName(name string) {
    	this.name = name
    }
    

    3. 接口

    golang接口中没有变量,只有方法。

    对于java中的多态描述:重载和重写两种多态。但是在golang中无法对方法进行重载,因为golang是一门面向函数编程的语言。所以golang可以通过重写来实现多态,而且是接口和子类之间的重写。

    package main
    
    import "fmt"
    
    func main() {
    	ben := &Ben{"benchi"}
    	ao := &Ao{"aodi"}
    	ToString(ben)
    	ToString(ao)
    }
    
    type Car interface {
    	GetName() string
    	SetName(name string)
    }
    
    func ToString(car Car) {
    	fmt.Println(car.GetName())
    }
    
    type Ben struct {
    	name string
    }
    
    func (ben Ben) GetName() string {
    	return ben.name
    }
    
    func (ben *Ben) SetName(name string) {
    	ben.name = name
    }
    
    type Ao struct {
    	name string
    }
    
    func (this Ao) GetName() string {
    	return this.name
    }
    
    func (this *Ao) SetName(name string) {
    	this.name = name
    }
    

    4. 类型断言

    golang 类型断言和java中的instanceof 关键字相似,但是又比这个关键字高级,好用,实现方式val.(T)

    func main() {
    	var x interface{}
    	x = 4
    	if y, ok := x.(int); ok {
    		fmt.Println(y)
    	}
    }
    

    断言接口子类

    package main
    
    import "fmt"
    
    func main() {
    	ben := Ben{"benchi"}
    	ao := Ao{"aodi"}
    	ToString(ben)
    	ToString(ao)
    }
    
    type Car interface {
    	GetName() string
    }
    
    func ToString(car Car) {
    	if ben, ok := car.(Ben); ok {
    		fmt.Println(ben.GetName())
    	} else if ao, ok := car.(Ao); ok {
    		fmt.Println(ao.GetName())
    	} else {
    		fmt.Println("other type")
    	}
    }
    
    type Ben struct {
    	name string
    }
    
    func (ben Ben) GetName() string {
    	return ben.name
    }
    
    type Ao struct {
    	name string
    }
    
    func (this Ao) GetName() string {
    	return this.name
    }
    

    如下代码,有什么问题呢?此时我们使用指针类型是实现了接口notify的方法,那么在SendNotify(u notify)中我们必须使用子类的指针作为参数传递到该函数,如果我们使用值类型实现接口notify的方法,例如func (this user) Notify()这样既可以使用指针也可以使用值传递参数。

    package main
    
    import "fmt"
    
    func main() {
    	u := &user{"hello"} //此时必须传递指针参数
    	SendNotify(u)
    }
    
    type notify interface {
    	Notify()
    }
    
    type user struct {
    	name string
    }
    
    //指针实现接口
    func (this *user) Notify() {
    	fmt.Println(this.name)
    }
    
    func SendNotify(u notify) {
    	u.Notify()
    }
    

    这是为什么呢?

    对于一个方法method(param T) 可以接受值类型指针类型的参数,method(param *T) 仅仅可以接受指针类型的参数。

    5. 闭包

    java中有函数式编程,集合框架中有一个消费型函数forEach,我们在golang中通过闭包实现该函数

    package main
    
    import "fmt"
    
    func main() {
    	data := []int{1,2,3,4,5}
    	forEach(data, func(index int, value interface{}) {
    		fmt.Println(index, value)
    	})
    }
    
    func forEach(data []int, f func(int, interface{})) {
    	for index, value := range data {
    		f(index, value)
    	}
    }
    

    2. golang 杂项

    2.0 defer

    defer会在函数或者方法结束前被调用,和Java中finally相似

    func main() {
    	/**
    	first
    	hello world
    	defer is called
    	 */
    	say()
    }
    
    func say() {
    	fmt.Println("first")
    	defer fmt.Println("defer is called")
    	fmt.Println("hello world")
    }
    
    //由于return了,所以return后面的语句不会被执行
    func say2() {
    	fmt.Println("first")
        return
    	defer fmt.Println("defer is called")
    	fmt.Println("hello world")
    }
    

    defer使用场景:错误处理,关闭资源,释放锁,后续会见到这些使用操作

    2.1 错误处理

    这里诉说的错误处理和Java中的异常处理一样,在java语言中错误处理一般都是try...catch…finally,而在golang语言中通过三个关键字对错误尽心处理:(defer recover) panic

    1. defer+recover来捕获异常
    func catchError() {
    	defer func() {
    		err := recover()
    		if err != nil {
    			fmt.Println("出现异常", err)
    		}
    	}()
    	a := 10
    	b := 0
    	x := a / b
    	fmt.Println(x)
    }
    
    1. 自定义异常
    func catchError() {
    	//在这里捕获处理,如果不进行捕获,则程序会崩溃
    	defer func() {
    		err := recover()
    		if err != nil {
    			fmt.Println("出现异常", err)
    		}
    	}()
    	err := selfError()
    	//向外抛出异常
    	panic(err)
    }
    
    func selfError() error {
    	return errors.New("自定义异常")
    }
    

    2.2 日志

    package main
    
    import "log"
    
    func main() {
        //  info:2019/02/04 16:47:25 LoggerDemo.go:6: message
    	log.Println("message")
    }
    
    func init() {
    	log.SetPrefix("info:")
    	log.SetFlags(log.Ldate | log.Ltime | log.Lshortfile)
    }
    
    func main() {
    	log.Println("message")
    	//Fatalln执行之后调用:os.Exit(1), 退出程序,后续程序不再执行
    	log.Fatalln("打印日志,程序退出")
    	fmt.Println("还会执行吗")
    }
    

    定制日志记录器

    package logger
    
    import (
    	"log"
    	"os"
    	"io"
    )
    
    var (
    	Debug *log.Logger  //仅仅输出到控制台
    	Info *log.Logger
    	Warning *log.Logger
    	Error *log.Logger
    )
    
    const (
    	logFlag = log.LstdFlags | log.Lshortfile
    )
    
    func init() {
    	file, error := os.OpenFile("info.log", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)
    	if error != nil {
    		panic(error)
    	}
    	Debug = log.New(os.Stdout, "debug:", logFlag)
    	Info = log.New(io.MultiWriter(file, os.Stdout), "info:", logFlag)
    	Warning = log.New(os.Stdout, "waring:", logFlag)
    	Error = log.New(io.MultiWriter(file, os.Stderr), "error:", logFlag)
    }
    

    测试

    package main
    
    import "logger"
    
    func main() {
    	logger.Debug.Println("debug")
    	logger.Info.Println("create a info log")
    	logger.Error.Println("create a errr log")
    }
    

    2.3 IO流

    package main
    
    import (
    	"os"
    	"fmt"
    	"bufio"
    	"io"
    	"io/ioutil"
    )
    
    func openFile() {
    	file, err := os.Open("info.log")
    	if err != nil {
    		fmt.Println("文件错误", err)
    	}
    	defer file.Close()
    
    	reader := bufio.NewReader(file)
    	for {
    		str, err := reader.ReadString('
    ')
    		if err == io.EOF { //表示读取完毕
    			break
    		}
    		fmt.Print(str)
    	}
    }
    
    //读取内容到内存中
    func openFile2() {
    	data, err := ioutil.ReadFile("info.log")
    	if err != nil {
    
    	}
    	fmt.Print(string(data))
    }
    
    func writeFile() {
    	file, err := os.OpenFile("hello.txt", os.O_WRONLY| os.O_CREATE | os.O_APPEND, 0666)
    	if err != nil {
    		fmt.Println("创建文件错误")
    		return
    	}
    	defer file.Close()
    
    	writer := bufio.NewWriter(file)
    	for i := 0; i < 5; i++ {
    		writer.WriteString("写入数据:
    ")
    	}
    	writer.Flush() //将缓冲区内容写入到文件中
    
    }
    
    //判断文件是否存在
    func IsExist() {
    	_, e := os.Stat("info2.log")
    	if e != nil {
    		exist := os.IsNotExist(e)
    		fmt.Println(exist)
    	}
    }
    

    2.5 json

    package main
    
    import (
    	"encoding/json"
    	"fmt"
    	"time"
    )
    
    type Book struct {
    	Title string
    	Author string
    	Publish time.Time
    }
    
    
    //序列化map
    func serializeMap() {
    	student := make(map[string]interface{})
    	student["name"] = "闰土"
    	student["age"] = 20
    	student["class"] = "大一"
    	bytes, err := json.Marshal(student)
    	if err != nil {
    		fmt.Println("序列化错误")
    	}
    	fmt.Println(string(bytes)) //{"age":20,"class":"大一","name":"闰土"}
    }
    
    //序列化结构体
    func serializeStruct() {
    	book := Book{"青春","itcloud", time.Now()}
    	bytes, _ := json.Marshal(book)
    	fmt.Println(string(bytes)) // {"Title":"青春","Author":"itcloud","Publish":"2019-02-05T11:14:51.094709+08:00"}
    }
    
    func deserializeMap() {
    	var student map[string]interface{}
    	data := `{"age":20,"class":"大一","name":"闰土"}`
    	err := json.Unmarshal([]byte(data), &student)
    	if err != nil {}
    	fmt.Println(student)
    }
    
    func deserializeStruct() {
    	var book Book
    	bookStr := `{"Title":"青春","Author":"itcloud","Publish":"2019-02-05T11:14:51.094709+08:00"}`
    	json.Unmarshal([]byte(bookStr), &book)
    	fmt.Println(book)
    }
    
    

    2.6 网络编程

    1. TCP

    客户端

    package main
    
    import (
    	"bufio"
    	"fmt"
    	"net"
    	"os"
    )
    
    func main() {
    
    	conn, _ := net.Dial("tcp", "127.0.0.1:8088")
    
    	reader := bufio.NewReader(os.Stdin)
    	line, _ := reader.ReadString('
    ')
    
    	n, _ := conn.Write([]byte(line))
    
    	fmt.Println(n)
    
    }
    
    

    服务端

    package main
    
    import (
    	"fmt"
    	"net"
    )
    
    func main() {
    	listener, err := net.Listen("tcp", "127.0.0.1:8088")
    	if flag := Checkout(err, "监听开启错误"); !flag {
    		return
    	}
    	defer listener.Close()
    
    	for {
    		fmt.Println("等待客户端建立连接...")
    		conn, err := listener.Accept()
    		if flag :=  Checkout(err, "打开连接失败"); flag {
    			fmt.Printf("conn= %v, ip = %v
    ", conn, conn.RemoteAddr().String())
    		}
    		go process(conn)
    
    	}
    
    
    }
    
    func process (conn net.Conn) {
    	defer conn.Close()
    	for {
    		buf := make([]byte, 1024)
    		readLen, err := conn.Read(buf)
    		if flag := Checkout(err, "读取失败"); !flag {
    			return
    		}
    		fmt.Println(string(buf[:readLen]))
    	}
    }
    
    func Checkout(err error, msg string) bool {
    	if err != nil {
    		fmt.Println(msg, err)
    		return false
    	}
    	return true
    }
    
    

    2. http

    func main() {
    	http.HandleFunc("/echo", echo)
    	http.ListenAndServe(":8080", nil)
    }
    
    func echo(w http.ResponseWriter, r *http.Request) {
    	body, err := ioutil.ReadAll(r.Body)
    	if err != nil {
    		w.Write([]byte("get body error"))
    		return
    	}
    	strlen, err := w.Write(body)
    	if err != nil && strlen != len(body) {
    		w.Write([]byte("write a error"))
    
    	}
    }
    
    package main
    
    import (
    	"net/http"
    	"time"
    )
    
    //自定义handler
    func main() {
    	myHandler := &SelfHandle{format: time.RFC1123}
    	http.Handle("/time", myHandler)
    	http.ListenAndServe(":8080", nil)
    }
    
    type SelfHandle struct {
    	format string
    }
    
    func (h *SelfHandle) ServeHTTP(w http.ResponseWriter,  r *http.Request) {
    	forTime := time.Now().Format(h.format)
    	w.Write([]byte("time is " + forTime))
    }
    

    多路复用处理器

    package main
    
    import "net/http"
    
    //多路复用处理器
    func main() {
    	mux := http.NewServeMux()
    	mux.HandleFunc("/hello", hello)
    	mux.HandleFunc("/world", world)
    	server := &http.Server{Addr: ":8080", Handler: mux}
    	server.ListenAndServe()
    }
    
    func hello(w http.ResponseWriter, r *http.Request) {
    	w.Write([]byte("hello"))
    }
    
    func world(w http.ResponseWriter, r *http.Request) {
    	w.Write([]byte("word"))
    }
    
  • 相关阅读:
    伪元素 first-letter
    html语义化 -------<fieldset>和<legend>
    《ASP.NET MVC4 WEB编程》学习笔记------ViewBag、ViewData和TempData的使用和区别
    《ASP.NET MVC4 WEB编程》学习笔记------.net mvc实现原理ActionResult/View
    《ASP.NET MVC4 WEB编程》学习笔记------RenderBody,RenderPage,RenderSection
    《转》Visual Studio 2010 终极定制安装精简方法
    《转》IIS中配置通配符应用程序映射
    IIS安装时,添加/编辑应用程序扩展名映射 确定按钮不可用。
    异常:操作可能会破坏运行时稳定性
    petri网学习心得
  • 原文地址:https://www.cnblogs.com/hu1056043921/p/10312072.html
Copyright © 2020-2023  润新知