Go语言入门——进阶语法篇(三)
文章目录
- 进阶语法
- 指针
- 基本指针
- 高级指针
- 指针总结
- 面向对象
- 概述
- 对象
- 类
- 结构体
- 定义与初始化
- 添加方法
- 方法的注意事项
- 类型别名与类型定义的区别
- 工厂函数
- 接口
- 接口声明
- 接口实现
- 空接口
- 类型断言与类型查询
- 接口总结
- 面向对象三大特性
- 封装
- 继承
- 多态
- 欢迎关注我的公众号:编程之路从0到1
进阶语法
指针
基本指针
Go语言虽然存在指针,但是远比C语言指针简单,且Go语言基本指针不能直接进行指针运算。
Go语言基本指针用法和C语言几乎相同
&
取地址符*
解引用运算符
func main() {var num int// 声明指向int类型的一级指针 ptrvar ptr *int// 声明指向一个指针的二级指针 pptrvar pptr **int// 取变量地址,赋值给指针ptr = &num // 取指针地址,赋值给二级指针pptr = &ptr// 通过指针修改变量的值*ptr = 10fmt.Printf("num = %d\n", num )fmt.Printf("解引用: *ptr = %d\n", *ptr )fmt.Printf("解引用: **pptr = %d\n", **pptr)
}
人们极容易对值类型、引用类型、指针类型三个概念混淆,特别是将引用和指针混淆。指针是指一个保存内存地址的变量;而值是指的数据本身,值类型表示这个变量代表的就是数据本身,而不是数据的内存地址。引用则最容易产生歧义的说法,在C++中存在一种引用类型,它表示的是变量的别名,因此C++中的引用和指针是两种不同的类型。而我们在Go中指的引用类型,是指特定的几个类型,分别是slice
、map
、chan
、interface
,通常它们在内部封装了真实数据的指针,因此这些类型并不是值类型,称呼为引用类型。人们习惯于把指针指向真实数据的内存空间这一现象称呼为引用,即表示对值所在的内存空间的一种引用。
高级指针
为了使Go语言的指针也能像C语言那样能直接操作内存,Go提供了unsafe
包,正如其名,它是不安全的,官方不推荐的用法,不到万不得已不建议使用。
unsafe
包主要提供了两种类型,三个函数
unsafe.Pointer
:通用指针类型,主要用于转换不同类型的指针,不能进行指针运算uintptr
:主要用于指针运算,uintptr
无法持有对象,uintptr
类型的目标会被GC回收
函数
Alignof
Offsetof
Sizeof
以上三个函数中,主要说一下Sizeof
,它类似于C语言的sizeof
运算符,获取一个变量所占据的字节数。
package mainimport ("fmt""unsafe"
)func main() {var price float64var pi float32var num intvar ptr *intptr = &numfmt.Printf("float64 size is %d\n", unsafe.Sizeof(price))fmt.Printf("float32 size is %d\n", unsafe.Sizeof(pi))fmt.Printf("int size is %d\n", unsafe.Sizeof(num))fmt.Printf("*int size is %d\n", unsafe.Sizeof(ptr))
}
打印结果:
float64 size is 8
float32 size is 4
int size is 8
*int size is 8
转化指针,强行进行指针运算
package mainimport ("fmt""unsafe"
)func main() {var arr [5]int = [5]int{1, 2, 3, 4, 5}var p *int = &arr[0]// 将普通指针转为 Pointer类型指针var tmp unsafe.Pointer = unsafe.Pointer(p)// 将Pointer类型转为uintptr后做指针加法运算// 运算完成后,需将uintptr类型重新转为Pointer// 再将Pointer重新转为普通类型 *int指针,最后解引用fmt.Printf("arr[1] = %d\n", *(*int)(unsafe.Pointer(uintptr(tmp) + unsafe.Sizeof(p))))fmt.Printf("arr[2] = %d\n", *(*int)(unsafe.Pointer(uintptr(tmp) + unsafe.Sizeof(p)*2)))fmt.Printf("arr[3] = %d\n", *(*int)(unsafe.Pointer(uintptr(tmp) + unsafe.Sizeof(p)*3)))
}
打印结果:
arr[1] = 2
arr[2] = 3
arr[3] = 4
可以看到,想要在Go语言中进行指针运算,是相当麻烦的,Go语言本身也不建议我们使用指针运算。
另外一定要注意,只有uintptr
才能做指针运算,且GC并不把uintptr
当做指针,所以uintptr
不能持有对象, 它可能会被GC回收, 导致出现无法预知的错误。 而Pointer
类型指针指向一个对象时, GC则不会回收这个内存对象
指针总结
- Go指针主要用于传递结构体地址,防止不必要的内存拷贝,提升性能
- Go语言使用
nil
表示空指针 - Go无需手动管理堆内存,Go编译器会基于逃逸分析来确定内存分配在堆上还是栈上,因此无需对指针进行释放,堆上的内存由GC处理
面向对象
概述
所谓面向对象,是相对于面向过程而言的。那什么是面向过程呢?C语言就是一种典型的面向过程的编程语言。其实过程,也就是所谓的步骤。有一个经典例子是这样的,如何把大象放进冰箱?
- 把冰箱门打开
- 把大象放进去
- 把冰箱门关上
有些人可能会觉得荒诞,大象怎么能放得进冰箱呢?然而这就是面向过程的思维方式,C语言代码如下
void openDoor(){}
void put(void *){}
void closeDoor(){}int main(){// 打开门openDoor();// 放进去put(obj);// 关上门closeDoor();
}
每一个步骤对应到代码其实就是一个函数,每一个函数实现一个功能,然后分步调用这些函数。这些函数可能是我们自己写的,也可能是别人写的,函数实际上是一个黑盒模型,这个盒子是封闭的,我们不知道里面有什么,只知道这个盒子有一个入口和一个出口,就如同ATM机,我们把卡插到入口,另一边出口就冒钱出来了,至于具体的,钱是怎么冒出来的,这不是我们关心的。回到上面的例子,大象能不能放进冰箱,这也不是我们关心的,总之这个函数就是把大象放进冰箱的函数,只管调用它就好了。
有了这种面向过程的思维方式,编程就变得简单清晰有条理了,我们可以先把整个架子先搭起来,所有的函数先空实现,整个架子建好了,再慢慢去实现这一个个函数的具体细节。这跟建房子一样,先把钢结构架子搭起来,然后再慢慢码砖砌墙,最后才是室内装修。
随着软件业的发展,需求越来越复杂,人们发现面向过程的思维模型太简单了,已经无法胜任日益复杂的软件需求了,于是就出现了面向对象的思维方式。面向对象既是一种思维模型,也是一种代码的组织形式。
面向对象核心的载体是类和对象。那什么是类?什么是对象呢?
对象
要说清楚这个问题,得先解释什么是对象,不然还怎么去面向对象呢。在面向对象的哲学里,有一句话是“一切皆对象!”对象一词实际上是从英语翻译过来的,这个翻译其实是不准确的,最重要的就是没有指明这个概念的内涵。它的英文object
实际上表达的是具体事物,客观事物,客体的意思。其实就是将具体事物抽象化,用一句星爷电影《功夫》中的台词来解释就是“那个谁”的意思,就是将一切的具体事物,抽象出一个共同的指代模型,你也可以说“那个东西”、“那个事物”,你在说这句话时,一定是指的一个具体存在的东西,而不是一个空泛的虚无的东西,这就是对象的特点。
类
了解了对象,我们不禁要问,编程中怎么创建对象,怎么运用对象呢?可以试想一下,假设我们现在想要描述猫这种动物,该怎么做?
首先可以观察具体的猫,然后将所有猫都具备的特征提取出来,抽象出来,这个抽象出来的模型也就是类。例如,猫都有尾巴,有毛,圆眼竖瞳,喜欢睡觉,昼伏夜出,会抓老鼠,会喵喵叫,喜欢吃鱼等等。这里我们就提取几个特征,形成一个猫类
- 圆眼竖瞳
- 有皮毛
- 吃鱼
- 抓老鼠
- 睡觉
有了类,我们就可以判断一只猫是否属于猫类,也可以根据这个类批量创造猫。可以看出,类其实就是一个设计蓝图,或者说是一个模具,所有依据这个蓝图创造的具体的猫都是这个类的一个对象。类就是一个图纸,对象就是这个图纸的具体事物。
类所包含的特征,我们通常分为两种类型,属性和行为。属性是静态的描述,行为是动态的特征。以上面的猫类为例
属性 | 行为 |
---|---|
圆眼竖瞳 | 吃鱼 |
有皮毛 | 抓老鼠 |
睡觉 |
行为往往是以动词开头,在编程中用使用函数来表示,而属性则使用变量来表示。纯粹的面向对象编程语言是Java和C#,其次支持面向对象的还有C++和Python等。Go与这些编程语言不同,它没有在语法层面完全支持面向对象,譬如它没有类的概念,Go只能像C语言一样,使用结构体来模拟类,但是Go语言的结构体与C++中的结构体不同,C++的结构体并不是真正的结构体,它实际上就是一个类,C++中结构体与类的差别不大,而Go语言的结构体,更接近C语言的结构体。
结构体
Go语言的结构体类似于C语言的结构体,Go语言使用结构体来模拟类,因此,我们可以简单的将Go的结构体看做是一个类,通过这个结构体生成的也就是该类的对象。
定义与初始化
// 定义学生结构体,即等同于学生类
type Student struct{id uint64name stringage intscore float64
}func main() {// 声明结构体变量 stuvar stu Student// 四种创建结构体对象的型式,即创建对象stu1 := new(Student)stu2 := Student{}// 创建时初始化。按属性顺序初始化stu3 := Student{1001, "Alice", 18, 259.5}// 声明式初始化stu4 := Student{id:1003,name: "Tom", age: 19}// 结构体对象的属性访问与赋值stu2.name = "John"stu2.id = 1002stu4.score = 190.5
}
定义结构体的格式,注意,定义结构体属性时,不要使用var
关键字
type 结构体名 struct{字段(属性)
}
在Go语言中,未进行显式初始化的变量都会被初始化为该类型的零值,结构体的属性字段也是一样
另外要注意一点,在C语言中,结构体指针调用成员变量时,使用->
操作符,而Go语言中都是使用.
操作符,Go语言会对结构体指针做自动转换然后再访问成员
// 结构体指针pStu := &Student{}pStu.name = "John"// 等价于以下调用。Go会先解引用然后在访问成员(*pStu).name = "John"
添加方法
方法就是一种特殊的函数,对应到面向对象类的概念中,也就是所谓的行为。在Go语言中,方法和函数最显著的区别是多了一个接收者的参数。
package mainimport ("fmt""math"
)// 定义结构体
type Point struct{X,Y float64
}// 为结构体添加SetX方法
func(this *Point)SetX(x float64){this.X = x
}// 为结构体添加SetY方法
func(this *Point)SetY(y float64){this.Y = y
}// 为结构体添加GetDistance方法
func(this *Point)GetDistance() float64{return math.Sqrt(this.X*this.X + this.Y*this.Y)
}func main() {p := Point{3,4}// 使用结构体对象调用方法fmt.Println(p.GetDistance())
}
定义结构体方法格式:
func(接收者)方法名(参数列表) 返回值列表 {}
方法与函数唯一的区别就是多了接收者,它位于关键字func
和方法名之间,它的类型就是需要添加方法的结构类型,该参数通常使用结构体指针,参数名任意,不过推荐使用this
或self
,这里接收者的作用相当于C++中的this
指针,或者Python中的self
。
方法的注意事项
在Go语言中,不仅仅是结构体有方法,所有自定义类型都可以添加方法
// 将int 声明为新类型Integer
type Integer intfunc(this Integer)Add(a int) int{return int(this) + a
}func main() {var num Integer = 21fmt.Println(num.Add(9))
}
类型别名与类型定义的区别
在Go1.9版本中引入了新特性类型别名。在此之前,type
关键字只能用于定义新类型,1.9之后,可以用于定义类型别名。
// 定义新类型
type 新类型名 原类型名// 定义类型别名
type 类型别名=原类型名
那么定义新类型和定义类型别名有什么区别呢?
// 定义类型别名
type Integer1=int// 定义新类型
type Integer2 intfunc main() {var num int = 1var a Integer1a = num //不会报错var b Integer2b = num //报错
}
类型别名与原类型是完全等同的,而定义的新类型与原类型是不同的,因此将原类型直接赋值给新类型会报错,相应的,定义新类型都可以绑定方法,而使用类型别名则不一定,如上例中,原类型int
是不能绑定方法的,因此Integer1
也是不能绑定方法的。在C语言中,typedef
关键字正是用于定义类型别名的,因此要注意Go语言的区别。
工厂函数
结构体是没有所谓的构造方法的,因此说Go语言的面向对象不是纯粹的面向对象。通常的,可以创建一个名为NewXXX
的工厂函数用来专门创建结构体的实例对象。
func NewPoint(x,y float64) *Point{return &Point{x,y}
}
接口
其实接口是我们生活中常接触的概念,最具代表性的是我们手机的充电接口。在智能手机之前的时代,不同的手机都有专用充电器,每一种的插口都是不同的,这给我们生活造成了很大不便,如果一家人出行,得带一大堆充电器,有手机、数码相机、mp3等等电子产品,后来
Mini USB
接口开始流行,各大电子厂商都遵循这种接口标准,包括按摩仪、剃须刀、电动牙刷等等,从此开始,充电器变得可以通用了,再之后安卓智能手机流行,出现了新的Micro USB
接口,到今天仍然是安卓手机最主流的数据、充电接口。目前,新一代手机数据接口type-C
也开始逐渐普及。
从上例的物理接口中我们可以得到启示,接口实质上是一种通用的标准或协议,它规范了某种行为特征,而规范接口的好处在于可以即插即用,非常方便。假设手机没电了,我们只需要借一个与手机接口匹配的充电器即可,我们不再关心充电器的具体情况,比如电压、电流等参数,在我们的意识里,只要接口能对上就是可以用的。
实际上,面向对象开发中的所谓接口,其概念正是来自生活中,它的特点跟优势与上例中的物理接口是类似的。Go语言中的接口可以用来定义一组不用实现的方法。如同Java中的抽象方法,C++中的虚函数。与Java等语言不同的是,Go的接口不需要显式的实现。
// 声明接口
type Phone interface{// 声明一个打电话的方法Call(number string)bool// 声明一个发短信的方法SendMessage(number, text string)bool
}// 声明一个结构体,并隐式实现Phone 接口
type HuaWei struct{}func(this *HuaWei)Call(number string)bool{fmt.Println("呼叫:"+number)return true
}func(this *HuaWei)SendMessage(number, text string)bool{fmt.Println("发送给:"+number+" , "+text)return true
}func main() {// 声明一个接口类型变量 phone var phone Phone// 创建结构体对象h := &HuaWei{}// 通过赋值,初始化接口类型变量phone = h// 使用接口变量调用方法phone.Call("123456")phone.SendMessage("10086","查询话费")
}
我们从手机中抽象出两个功能,分别是打电话和发短信,只要具有这两个功能的电子产品,我们就认为它是手机。声明一个Phone
接口,它具有两个空方法Call
和SendMessage
,再定义一个具体的结构体HuaWei
,然后给HuaWei
结构体绑定两个Phone
接口的具体实现方法,这时候HuaWei
结构体即隐式的实现了Phone
接口,我们就可以说HuaWei
是Phone
接口的一个具体实现。当然,除了HuaWei
还有很多其他品牌手机,我们还可以定义更多不同的结构体来实现Phone
接口,总之,只要实现了Phone
接口,它就是手机。我们在使用的时候,将具体的结构体对象赋值给接口类型对象,然后使用接口类型对象去调用方法,而不是使用具体的结构体HuaWei
的实例对象去调方法。举个例子,当我们需要打电话发短信时,根本不关心具体是什么手机,只要能打出去,能发出去就可以了,这是手机通用的功能,甚至非智能手机都能做到,这种思想也就是面向对象编程中常说的解耦合,通用的功能不要和特定的对象关联起来,如上例中使用具体结构体的h
变量调用方法,这就是和特定对象关联了。在Go语言中,正是使用接口来实现解耦合。
接口声明
格式
type 接口名 interface{方法声明1方法声明2
}
注意,接口中的方法声明不需要func
关键字,不需要声明接收者,也不需要方法体(不需要花括号),其他的和普通的函数声明一致。
即
方法名 + 函数签名
接口实现
Go中的接口实现是一种隐式实现,即某个自定义类型中包含全部的接口方法的实现,则这个自定义类型自动实现该接口。因此要注意,除了结构体可以实现接口,通过type
关键字创建的新类型都可以实现接口。另外的,一个自定义类型是可以实现多个接口的,只要实现了多个接口的所有方法,它就会自动实现这些接口。
空接口
在面向对象编程中,通常有超类的概念,即所有的类都默认继承某个类,例如Java和Python中Object,而在Go语言中,也有一个所有类型都默认实现的接口——空接口。Go语言目前没有泛型的概念,通常就需要使用空接口来实现类似泛型的功能。
空接口是一个匿名的接口,它不包含任何方法
interface{}
Go语言中的数组和切片只能存放相同的数据类型,我们知道Python中的列表是可以存放任意类型的数据的,那我们如何让数组方法不同的数据类型的元素呢?答案就是借助空接口,声明一个空接口类型的数组
type MyType struct{}// 声明一个interface{}类型的数组,它的长度是5,
objs := [5]interface{}{1,"abc",1.5,[1]int{0},MyType{}}
所有类型都默认实现空接口,包括基本数据类型,这表示所有类型都是interface{}
类型的子类型,因此interface{}
类型数组就可以装下所有类型的数据。
类型断言与类型查询
假如一个数组或切片是interface{}
类型的,那么我们遍历这个数组时,怎么判断该数据的具体类型是什么呢?
在Go语言中,可以使用多种方式判断一个变量的具体类型或是否实现了某接口,这里主要说明一下类型断言与类型查询
类型断言
func main() {objs := [5]interface{}{1,"abc",1.5,[1]int{0},MyType{}}for _,it := range objs{// 类型断言,如何匹配括号中的类型,则ok为trueif o,ok := it.(string); ok{fmt.Printf("string类型:%s\n",o)}if o,ok := it.(int);ok{fmt.Printf("int类型:%d\n",o)}if o,ok := it.(interface{});ok{fmt.Printf("interface{}类型:%T\n",o)}}
}
类型查询
func main() {objs := [5]interface{}{1,"abc",1.5,[1]int{0},MyType{}}for _,it := range objs{// 接口查询,使用switch结构switch v := it.(type){case string:fmt.Printf("string类型:%s\n",v)case int:fmt.Printf("int类型:%d\n",v)case [1]int:fmt.Printf("[1]int类型:%T\n",v)case interface{}:fmt.Printf("interface{}类型:%T\n",v)default:fmt.Println("未知类型")}}
}
接口总结
- 接口中的方法必须是空实现,没有方法体
- 接口中不能声明变量
- 接口不能创建实例,只能通过赋值初始化。赋值对象可以是实现了接口的自定义类型,也可以是一个接口类型
- Go接口只能隐式实现,即实现接口包含的全部方法
- 除了结构体,其他任意自定义类型都能实现接口
- 所有类型,包括基本类型都默认实现空接口
- 接口是引用类型,其零值为
nil
面向对象三大特性
面向对象有三大特性,分别是封装、继承和多态,如果不能支持这三大特性,那么就不能说这门编程语言支持面向对象。
封装
即将类中抽象出来的属性和对属性的操作封装在一起,并把数据保护在内部,仅对其他包提供有限的操作权限。封装能隐藏实现细节,提供对数据的验证。
我们知道Java有四种包访问权限,C++也有private
和public
,而在Go语言中却并未提供关键字来设置访问权限,它更类似于Python,对包外仅提供可见与不可见两种权限,属性名(包括方法名)首字母大写,则包外可访问,小写则不可访问。Go语言主要通过结构体方法、包访问权限来实现封装特性。大家会发现,Go语言标准库提供的所有函数都是大写字母开头的,这就是为了让包外可访问。相比于其他语言,Go的封装格外别扭。
继承
继承的主要目的就是为了代码复用,更简单说就是为了少写代码,同也更容易构建类与类之间的结构化关系。
type Animal struct{age int
}func(this *Animal)Eat(){fmt.Println("吃东西……")
}func(this *Animal)Sleep(){fmt.Println("睡觉……")
}type Cat struct{Animal // 内嵌匿名结构体表示继承
}func main() {cat := Cat{}cat.age = 10cat.Eat()cat.Sleep()
}
上例中,定义了动物结构体,然后定义Cat
结构体,并让它继承于动物结构体,可以看到,在Cat
结构体中并未声明age
属性,也未绑定任何方法,但是Cat
继承了Animal
的属性和方法,因此它也具备了这些属性和方法。
当一个结构体与它继承的结构体存在同名属性或方法时,可以使用显式的方式访问
type A struct{Name stringid int64
}type B struct{AName stringnum int
}func main() {b := B{}b.A.Name = "xx"b.Name = "b"b.A.id = 1001
}
Go的结构体也可以多继承,多继承时存在同名字段,可以显式访问
type C struct{AB
}func main() {c := C{}c.A.Name = "xx"c.B.Name = "b"c.B.num = 100
}
除了结构体,接口也可以继承
type A interface{Method1()
}type B interface{Method2()
}type C interface{ABMethod3()
}
如上,C
接口继承了A
、B
接口,此时要想实现C
接口,就必须将A
、B
和C
中的方法全部实现
多态
实例对象具有多种形态,可以按照统一的接口来调用多种不同的实现,即面向对象所谓的多态。
Go语言的多态主要体现在两方面,函数参数多态和数组元素多态上面,而数组元素多态,就如同接口一节的interface{}
类型数组的例子。
// 声明一个宠物接口
type Pet interface{// 声明一个遛宠物功能函数Walk()
}// 声明猫结构体
type Cat struct{}func(this *Cat)Walk(){fmt.Println("遛猫……")
}// 声明狗结构体
type Dog struct{}func(this *Dog)Walk(){fmt.Println("遛狗……")
}// 声明熊结构体
type Bear struct{}func(this *Bear)Walk(){fmt.Println("战斗民族遛熊……")
}// 定义和宠物一起玩的函数
func PlayWithPets(p Pet){// 调用遛宠物的功能p.Walk()
}func main() {// 声明并初始化一个宠物数组,其元素分别是三种不同的结构体// 这就是多态的数组,实质就是一个泛型数组var pets [3]Pet = [3]Pet{&Cat{}, &Dog{}, &Bear{}}for i := 0;i < 3;i++ {// 函数参数上的多态,传入的实际上是三个不同的结构体对象PlayWithPets(pets[i])}
}
欢迎关注我的公众号:编程之路从0到1
Go语言入门——进阶语法篇(三)相关推荐
- Python语言入门这一篇就够了-学习笔记(十二万字)
Python语言入门这一篇就够了-学习笔记(十二万字) 友情提示:先关注收藏,再查看,12万字保姆级 Python语言从入门到精通教程. 文章目录 Python语言入门这一篇就够了-学习笔记(十二万字 ...
- C语言入门Part7--数组篇
C语言入门Part7–数组篇 **关键字:**数组常见问题及注意事项总结,字符串定义,一维数组在内存中的存储,sizeof()求数组长度的注意事项,sizeof()的用法注意,sizeof()和str ...
- FPGA笔记之verilog语言(基础语法篇)
文章目录 FPGA笔记之verilog语言(基础语法篇) 1. verilog 的基础结构 1.1 verilog设计的基本单元--module 1.2 module的使用 1.3 I/O的说明 1. ...
- NAS群晖DSM 进阶教程 篇三:DSM 4458 升级 DSM 4493 update7
WOW唤醒NAS手机APP: Windows Phone 8.1测试可用"Wake my PC"的详细信息 http://www.windowsphone.com/s?app ...
- Xamarin XAML语言教程基础语法篇大学霸
Xamarin XAML语言教程基础语法篇大学霸 前 言 Xamarin是一个跨平台开发框架.它可以用来开发iOS.Android.Windows Phone和Mac的应用程序.使用Xamarin框 ...
- Go语言入门--基础语法
Go语言入门系列文章目录 Go语言入门–基础语法 Go语言入门–流程语句 Go语言入门–数组和切片 集合(Map)(咕咕咕
- c语言圆周率计算_C语言入门这一篇就够了
c语言入门 C语言一经出现就以其功能丰富.表达能力强.灵活方便.应用面广等特点迅速在全世界普及和推广.C语言不但执行效率高而且可移植性好,可以用来开发应用软件.驱动.操作系统等.C语言也是其它众多高级 ...
- 0-c语言入门这一篇就够了-学习笔记(一万字)
内容来自慕课网,个人学习笔记.加上了mtianyan标签标记知识点. C语言入门 -> Linux C语言编程基本原理与实践 -> Linux C语言指针与内存 -> Linux C ...
- c语言for循环除法运算,C语言入门这一篇就够了
c语言入门 C语言一经出现就以其功能丰富.表达能力强.灵活方便.应用面广等特点迅速在全世界普及和推广.C语言不但执行效率高而且可移植性好,可以用来开发应用软件.驱动.操作系统等.C语言也是其它众多高级 ...
最新文章
- 深度学习为什么要resize_为什么要学习演讲与口才
- php和python交互-Python如何实现简单的用户交互程序(示例)
- 谈一谈Spring-Mybatis在多数据源配置上的坑
- spring基于注解的声明式事务控制
- 保证全对——2015年第六届蓝桥杯C/C++ B组部分解题报告
- 计算机专业408题目结构,2019考研408计算机组成原理知识:计算机系统层次结构
- django-查询-F对象-Q对象
- lightclients将于4月27日主持召开EIP-3074社区会议
- python2.7卸载出问题原因分析_怎么卸载python2.7
- rabbitmq视频教程,面试官:
- C++(八)— 死锁原因及解决方法
- 监管大屏系统_“警视” 警务情指一体大屏可视化决策系统
- WES7@IIC-China
- 周杰伦 jay《青花瓷》mp3 下载/试听/MV/在线播放
- 数据流图、业务流程图、E-R图、系统功能结构图、程序流程图
- php拼音首拼,php 实现 汉字转拼音
- Android音视频录制类MediaRecorder用法举例
- 201771010112罗松《面向对象程序设计(java)》第十七周学习总结
- 服务器带宽打开网页很慢,为什么网速很快,但打开的网页速度却很慢?
- 算法题--递归解法(化整思想、24点、全排列、单词迷宫解法加步骤)