Go in action


                                目录


一.Go简介
二.Go快速入门
三.包和工具
四.数组,分片和字典
五.Go的类型系统
六.并发
七.并发模式

八.标准库

九.测试(testing and benchmarking)




                                        Go简介

       计算机发展迅速,但是编程语言却没有跟上发展的步伐。我们现在使用的手机相比以前使用的计算机拥有更多的CPU内核数。高性能的服务器拥有64128或者更多内核,但是我们仍然用以前只有一个内核时的编程方法来应对多核的场景,这显然是不和时宜的。

       编程的艺术需要随着时代的发展而发展。大多数的程序不再是由一个开发者完成:它们是由一个团队,在不同的地方,不同的时间完成的。大的项目会被分解为许多小的模块然后分配给开发者,待完成任务后,会提交一个可用于整个应用的库或者包。

        现在的开发者和公司相比以前更相信开源软件的力量。Go语言会使代码的分享更加的简单。Go附带的工具使使用别人的开发包更容易,这也使分享自己的开发包更容易。

        在本章,你会看到Go和其他编程语言有何不同。Go重新思考传统的面向对象开发,虽然它仍然是一种有效的代码复用方式。Go使你更容易地充分利用服务器上所有的内核,并且减少大工程编译带来的开销。

        当你阅读本章时,你会感觉到形成Go的思想,以及并发模型和轻量级的工程管理系统。这本书是面向已经有其他语言开发经验并想学习GO的中级开发者。我们写这本书的目的是让你对Go有一个初步的了解。我们专注于阐明Go的细节和实现,包括语法,类型系统,并发,通道,测试等等。如果你想快速了解Go,以及Go的实现机制,这本书是一个很好的选择。

       我们希望你会感谢Go以及相关的工具,它们使你的开发工作更加的简单,最后,你也要感谢那些选择Go的开发者们。


用Go解决现代的编程挑战

      Go语言的开发团队想要解决现代开发者们面临的困境。在开始一个项目时,开发者们面临的问题是如何平衡快速开发和性能之间的问题。而Go则提供一个高性能且能快速开发的解决方案。

      当我们研究Go时,你会发现许多好的特性和精妙的语法。作为一个开发语言,Go有简明的语法和少量的关键词。Go有自己的工程管理系统,这使Go的工程编译更加的快速。作为一个Go的开发者,你会节约很多用于编译的时间。由于Go内建的并发特性,你的软件可以增加更多的可用资源,而不必担心多线程/多进程的问题。Go使用简单高效的类型系统,这使得面向对象开发变得更加简单,并且让你专注于代码复用。Go有自己的垃圾回收机制(GC),所以你不必自己管理内存。让我们一睹Go的这些特性吧。

 

开发进度

       用C/C++编译大的应用会花费大量的时间。Go提供轻量级的编译系统。当你构建你的Go程序时,编译器只需要知道你工程所在的目录,而不需要像C/C++等指明库之间的依赖关系。整个Go源文件树在现代硬件条件下编译时间要少于20秒。

      使用动态语言编写程序使你的开发更加的快速,因为程序的编程和执行不需要编译等中间过程。这之间的权衡是,动态语言不提供静态类型语言能提供的类型安全检测。


并发

       作为程序员,最困难的事之一是写一个尽可能多的利用硬件资源的应用。现代计算机有许多个核,但是大多数编程语言没有有效的利用这些额外的资源。它们大多都需要编写许多线程同步的代码,而这些代码非常容易出现错误。

       Go的同步机制支持的最强劲的特性就是协程(Goroutines),写成类似线程,但是它的实现比线程更简单,所消耗的内存更少。通道(channels

是一种可以在协程之间传递信息的数据结构它实现了协程间传递数据的模型,而不是让多个线程为了共同的资源的产生错误。接下来让我们了解协程的更多细节吧。


协程(Goroutines)

        协程是并行运行的函数,这包括了函数 的入口。在其他的编程语言中,你需要通过线程来实现相同的事情,但是在Go中许多的协程运行在单个线程中。例如,你需要实现一个Web服务器,这样你就要编写许多额外的代码。而在Go中,net/http库有内建协程机制。每个都会自动的运行在自己的协程中。

        如果你并行的执行相同的代码来完成一些事情,这协程很适合做这类事情。

        

          func  log(msg string) {

                  ...some logging code here
          }

          // Elsewhere in our code after we've discovered an error.
          go log("something dire happened")
           关键字go就是用来指定log函数以协程的方式与其他的协程并行执行。这意味着,你能够继续的执行剩下的指令,这使你能极大的提高程序的执行效率。正如这些阐述,协程所消耗的资源很少,所以成千上万的并发量对于Go来说并不是什么难事。


通道(channels)

          通道是使数据能在写成间安全传递的数据结构。他能帮助你避免许多在能使用共享内存的编程语言中遇到的问题。

          并发最困难的事是确保数据不会被其他并行的进程/线程/协程改变。当多个线程操作共同的数据而没有用到锁或者同步时,很有可能就会产生意想不到的结果。在其他的编程语言中,如果你要使用全局变量或者共享内存,那么你需要用到复杂的锁机制在避免对数据的并发操作。

          值得提醒的是,通道并不保证协程间的数据访问保护。如果数据的备份通过通道传递,那么每个协程都有属于本协程的一个备份,这使所有的协程都能安全的改变数据的。当数据的指针被传递时,协程也是需要同步读写的。


类型系统

           Go提供灵活的类型系统,他尽可能多地使我们能重用代码。他是面向对象编程的,但是避免了传统的麻烦。如果以前你要花一周的时间来设计你的抽象类或接口,那么你现在会对Go的类型系统产生惊讶。Go内嵌的类型系统使用组合的方式来重用函数。在其他面向对象的语言中,这些都要通过继承来实现,而这会使程序变得更加的臃肿。但是在Go中,类型就是由更小的类型组合而成的,这和传统的继承模型正好相反。

          另外,Go有自己独特的接口实现方式。你不需要声明你实现的接口;编译器会自动的检测你使用的类型是否实现了某个接口。Go标准库中的许多接口都是非常的简洁的,仅仅就是几个暴露的函数。


内存管理

          不合理的内存管理机制会导致程序的崩溃和内存泄漏,这也可能导致整个操作系统的崩溃。Go有自己的一套现代的垃圾回收机制,他替我们做了许多繁杂的工作。在其他的编程语言中,像C/C++等,你需要手动的申请一块内存,然后才能使用它,使用完之后,又需要手动的释放。如果你不能很好的组织内存分配和回收的代码,那么你的程序很可能由于内存泄漏而崩溃。去追踪每块内存不是一件容易的事情。


Hello Go

             

package main

import “fmt”

func main() {
       fmt.Println("Hello World!")
}



Go快速入门

         Go有自己优雅的编程语法,这使得对Go的编程变得有趣。Go语言的开发者开发这门新语言的目的是让它能够快速编程而不失去对底层结构的控制。这种平衡通过很少的关键字集合,内建函数以及语法实现的。Go语言提供可理解的标准库。这个标准库提供编程者编写实时Web和基于网络程序的核心包。


程序结构

       程序被分为几个不同的部分,并且运行在不同的写成中。接下来我们会解析这些代码。

                   

       cd $GOPATH/src/github.com/goinaction/code/chapter2
       - sample
          - data
               data.json   -- Contains a list of data feeds
          - matchers
               res.go         -- Matcher for searching res feeds
          - search            
               default.go   -- Default matcher for searching data
               feed.go       -- Support for reading the json data file
               match.go     -- Interface support for using different matchers
               search.go   -- Main program logic for performing search
          main.go             -- Program entry point
 

Main package

         这个程序的入口在main.go中。尽管它只有21行代码,但是还是 有些事是需要提醒的:

        package main

        import (
               "log"
               "os"

                _ "github.com/goinaction/code/chapter2/sample/matchers"
                "github.com/goinaction/code/chapter2/sample/search"
           )

         // init is called prior to main.
         func init() {
         // Change the device for logging to stdout.
         log.SetOutput(os.Stdout)
         }

         // main is the entry point for the program.
         func main() {
          // Perform the search for the specified term.
          search.Run("president")
         }

           每个Go的可执行程序都有两个独特的特性。其中一个就是都有唯一一个main函数。为了生成可执行程序,main函数是必须的。另外一个特性可以在代码第一行找到,那就是代码都必须属于一个包。你可以看见,main函数位于一个名为main的包中。如果你的包中不存在main函数,那么编译器就不能为你生成可执行文件。

            每个Go文件都属于一个包,main.go也不例外。会在第三章中对此作更详尽的解释,因为包是Go的一个重要特性。现在,理解包作为一个包的标识就像命名空间一样是很重要的。这使我们能够识别不同包中的同名函数。现在把你的注意力放在第三行到第九行上:     

import (
    "log"
    "os"
    _ "github.com/goinaction/code/chapter2/sample/matchers"
    "github.com/goinaction/code/chapter2/sample/search"
)
引入就是引入代码,使你有权限访问引入包类的标识符,例如类型,函数,常量和接口等。所有的在同一个包内的文件都必须使用同一个包名。





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值