初次接触Goland,使用Goland编写运行第一个Helloworld程序以及报的错误
首先声明:
本人第一次接触Golang,正在不断的学习,也是第一次使用Goland编译器,遇到了不少的疑惑,然后经过一些baidu,有了一些理解,可能存在不太准确的地方,希望如果发现我哪里有问题了以后可以及时的指出或讨论!
创建工程并成功运行第一个Helloworld程序
- 创建工程
这里我想说一下,我在网上搜索的时候发现了各种各样的创建工程的路径,看的我有点晕,我个人最终是参考了慕课网上的一个视频,然后将工程建在了我系统变量中设置的F:\Code\Go\下的src文件下,这里的话,我想强调一句,我的F:\Code\Go\下的src文件下有bin、pkg、src,这个是我参考一些csdn上博客对于go环境搭建上有的结构, bin包含编译后的代码、pkg包含包对象、src中包含Go源文件。
未完待续啊,先去接杯水,回来继续!
喝水归来,然后我写了半天的博客,然后我一开心休息了半天,然后忘记发布了,然后我又从这里开始了(微笑脸)
2.创建一个go文件
创建一个命名为Helloworld的go文件,我这里呢可以看到已经建好了这个文件。
3.编写Helloworld程序,然后成功运行
在文件中输入下列程序
然后在菜单栏Run下点击绿色小三角的Run就可以成功运行啦。
import "fmt"
func main(){
fmt.Println("Helloworld")
}
诺~现在就成功运行了Helloworld啦!
然而。。
现实中真的会这么顺利么?!请看下面
正当我们暗暗期待我们go语言学习的第一步要迈出去的时候!!emmm它报错了。
Error:Run after build is not possible
Main file has non main package or doesn’t contain main function
呜呜呜(问号沮丧脸咋回事啊)
别急看下面
请仔细对比下面这两个图!
当前出现问题时的代码图:
成功运行代码图:
想必各位已经看出了一些端倪,没错啊!
就是package部分啊!
按照我们正常之前学习别的语言的基础,相比这个包没个啥子错,但是。。
这里!要写成main!!千万要记住啊!
Helloworld程序中蕴含的点
再来看一下正确的这个程序代码奥!
- package main:Go程序都织成包
- import “fmt”:import语句用于导入外部代码(这个地方和其他语言是一样的奥~),标准库中的fmt包用于格式化并输出数据
- func main(){}:和c语言一样啦!main函数当然是主程序执行入口嘛!
- fmt.Println(“Helloworld”):就是用标准库中fmt包中的输出函数Println来输出我们想要的东西。
Go语言特点的简单归纳
- 开发速度
Go使用了比其他语言智能的编译器,简化了解决以来的算法,即在编译Go程序时,编译器只关注那些直接被引用的库,不想爪洼、C、C咔咔那样逐步搜索。
快!
但不安全。
Go不提供类型安全特性,所以不得不用大量的测试套件来避免运行时候出现类型错误的bug。 - 并发
并发是重要特性!!!之一。。。
主要体现在- goroutine
- 通道
goroutine(音译:哥辱町,不谢(hhh臭屁脸))类似线程,但比线程占用内存还少,所以使用它代码更少。Go中会使用同一线程来执行多个goroutine,通常能启动成千上万个goroutine。
goroutine可以与其他goroutine并行执行函数也可以和主程序并行执行。
每个接受到的请求都自动在其自己的goroutine中处理。
Go中的net/http库直接使用了内置的goroutine。
在一个系统线程上执行多个goroutine,多个goroutine的执行过程如下:
channel(我猜不需要音译,香奶奶哈哈哈,懂的都懂)是一种内置数据结构,可以让用户在不同goroutine之间同步发送具有类型的消息,进行安全的数据通信。通道(channel)可以帮用户避免其他语言中常见的共享内存访问问题。
通道这个结构保证了同一时刻只有一个goroutine会修改数据,通道用于在几个运行的goroutine之间发送数据。
使用通道在goroutine之间安全地发送数据如下图:
比如图中有三个和两个不带缓存的通道,第一个goroutine通过通道传数据给已经在等待装袋的第二个goroutine。所以在这两个之间数据是同步的,数据传输完毕后,两个goroutine都会知道数据已经完成。第二个和第三个之间原理同理,这种goroutine之间安全数据传输的方法不需要任何锁机制或同步机制了。
!!通道不提供跨goroutine的数据访问保护机制。
如果通过通道传输数据的一个副本,那么每个goroutine都有一个副本,各自对副本修改是安全的。当传输的是指向数据的指针时,如果读写由不同goroutine完成,那么每个goroutine需要额外同步动作。
这种模型类似宇在goroutine之间发消息,而非让多个goroutine争夺同一数据使用权。
- 类型系统
- 类型简单
- Go接口对一组行为建模
总而言之,就是Go采用组合设计模式,与传统的继承不同,即一个类型由其他更小的类型组合而成,用户定义的类型通常包含一组带类型的字段,用于存储数据,所以Go的类型与c的结构体很像。这种允许用户对行为进行建模不对类型进行建模就是Go独有的接口实现机制。
除此之外,接口用于描述类型的行为。如果一个类型的实例实现了一个接口,那么就意味着要执行一组特定的行为,Go不需要声明某个类型实现了某个接口,编译器会自动一个类型的实例是否符合正在用的接口,所以只需要实现这组行为。
参考鸭子类型:听这个东西叫起来像个鸭子就认为他可能就是只鸭子。
这里再对比一下继承和组合
继承形式如下:
这种感觉像是层层递进,万事万物都是由一个事物幻化而来,在幻化的过程中他们产生各自分化的部分,纵而有各自独特的功能,但是我个人感觉它很强调共性产生的个性。
组合形式如下:
组合感觉更像是一开始就强调万事万物都是一个个体,而万事万物之所以有所联系是因为能做相同的事,而非长得像或者是来自于一个家族就归类为一类,它强调能做什么,而非是什么而做什么,万物由各个功能各个小部分组合而成。
举个例子,我觉得可以说继承是一家人我爷爷是司机,我爸爸是工程师,我是假程序员,我们是一家人是因为都继承于我爷爷姓白,而我是我因为我会敲代码啊等等。
而组合像是我是我,我由做饭,敲代码,吃饭,睡觉等等可能不为我所知的骚操作骚行为组成,然后我是我,可能我的朋友也会敲代码、做饭、吃饭、睡觉等不为大家伙儿都不知道的骚操作做成。
(emmm咋有种越描越乱的感jio,大概我的理解emmmm好像说的又有点不太准确,。。没事看上面的图吧,图比我说的明白)
4. 内存管理
Go有现代化的垃圾回收机制,帮助我们管理内存,防止程序崩溃内存泄露等,这些使用内存前先分配内存用完释放内存等内存管理都交给专业编译器做,当然这种Go的垃圾回收机制会产生额外开销,但是方便省事就完事了!
(这个文章陆陆续续写了好久。。。真的很愧疚,拖延症要不起!希望我的学习可以持续记录下去)