前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >邻里街坊 golang入坑系列

邻里街坊 golang入坑系列

作者头像
随机来个数
发布2018-04-16 14:53:17
5420
发布2018-04-16 14:53:17
举报
文章被收录于专栏:写代码的海盗写代码的海盗

如果要追新或者怀旧,就点击https://andy-zhangtao.gitbooks.io/golang/content/ 。 博客园里面的文章基本和gitbook上面是保持同步的。

这几天看了几集<情满四合院>,这帮老演员演得真不错。也就不对标那些个小鲜肉了,他们除了长得好看,绯闻多。除此之外,没啥可关注的。老演员的一个眼神,一个动作都透着一股劲。这股劲能把人带到戏里面去,能让观众情不自禁的把自己带到那种氛围里面。 好像看的并不是别人家的事情,而是自己家的家长里短。 轮台词,没有华丽的辞藻。轮布景,就是在影棚里面搭出来的景。论演员,刚才说了,没有好看的小鲜肉。 轮特效,没有!论剧情,家长里短,好不出彩。可为啥能打动人,应该是演员的"敬业"精神吧。每个演员都把自己的角色演活了,演的非常生动,非常立体。就好像这些个演员都出自身边环境一样,没有丝毫的距离和陌生感。这种好片子太少了,好演员也太少,因此敬业的精神就显得越发珍贵了。

本节来聊Golang中的结构体(Struct)。Golang的缔造者绝对对C有着很深的感情,Golang从里到外都透着C的感觉。就感觉Golang是C的豪华升级版。结构体,又名Struct。除了在C/C++之外,很少会使用到。这里暂且不谈Struct在C里面的使用方式,只聊在Golang中应该如何使用。

首先来看Struct在Golang中处于什么作用。前文说过Golang中有几种基本数据类型,背不出来,屁股要挨打的哦?。但凡写过代码的人都清楚,只靠这几种数据类型是无法满足业务逻辑需要的,成熟的语言一定会满足用户自定义数据类型的需要。 在Golang当中,Struct就是为了满足自定义数据类型而诞生的。如果非要类比,那Struct就可以对标成Java里面的Class。比如下面:

代码语言:javascript
复制
type News struct{
    Title string
    Content string
    Date string
}

News就是一个标准的Struct,里面有三个属性。由此,可以推导出Struct的声明语法:

代码语言:javascript
复制
type name struct {
   member definition;
   member definition;
   ...
   member definition;
}

name是struct的名称,也可以理解成类名。member可以理解成成员变量,这里要注意,如果首字母大写,则属于public。如果小写,则属于private。而definition则是变量类型,这个类型可以是基本类型也可以是自定义类型,总之是合法数据类型就可以。

一旦声明完成,恭喜你,你拥有了一个独属于你的数据类型。但怎么使用呢?先来看初始化。最简单的方式:

代码语言:javascript
复制
myNews := News{
    Title:"xxx",
    Content:"xxxx",
    Date:"xxxx",
    }

这是最简单的初始化方式,其中不是每个变量都需要给值的,想给几个就给几个,想不给,那就直接 myNews := News{}。高兴就好!

初始化之后,就轮到使用了。 怎么用?最简单的方式:myNews.Title就可以了。 如果高兴,也可以仿照Java来个Setter/Getter函数。没关系,不用担心别人说三道四。黑猫白猫,最合适的就是好猫。只要结构清晰,团队成员看起来舒服,学习成本低。爱用哪个就用哪个。

到此,你就可以随心所欲,敞开了用成员变量。甭担心会出错,年轻人写代码不出错还叫年轻人嘛!反正错了在fix呗。如果说看到这里,你就认为Struct说完了,那就找个地方泡杯茶,然后再回来吧。 注意到没有,上面所有的内容都是变量,说白了,还没涉及到成员函数呢。没有函数的Struct,就是一具没有骨骼的肉体,所以下面上骨骼。

和Java不同,Golang的Struct函数不是定义在Struct内部的,而是在外部。例如:

代码语言:javascript
复制
type News struct{
    Title string
    Content string
    Date string
}

func (news *News)GetTitle(){....}

GetTitle就是News的成员函数,除了News的实例能调用。其它人无权调用。这里的写法是不是和以前讲解的函数声明方式不同?也没多什么,就多了一个"归宿"而已。我们告诉编译器,这个函数是属于News的。

在有的团队中(可能是Java转型过来的吧),喜欢声明成这样:

代码语言:javascript
复制
func (this *News)GetTitle(){ this.xxxx .... }

这样使用this会比较顺手。由此看出,news也好,this也罢。只是一个指代当前实例的指针名称而已。 叫啥都行,哪个顺手用哪个。反正只在函数内部生效。

有没有人会提问?这些都是实例方法(Java的说法),有没有静态方法?有呀!,把(this *News)拿掉,函数首字母大写,就是静态方法了。 也就是在此之前,我们一直在写的那些个代码。

Struct在Golang当中,说重要其实也不重要。因为就是一个自定义数据类型而已,无非是添加了一些成员变量,还有成员方法,只要注意首字母大小写就没问题了。 但如果说不重要吧,也有失偏颇,Golang代码中的大部分都是依靠各种各样的Struct来实现的。 因此对于Struct来说,战略上藐视,战术上重视比较合适。

因为Struct也是一种数据类型,所以以前说的各种变量使用场景,这里都适用。比如,将一个Struct当做参数传入函数中:

代码语言:javascript
复制
package main

import "fmt"

type Books struct {
   title string
   author string
   subject string
   book_id int
}
func main() {
   var Book1 Books    /* Declare Book1 of type Book */
   var Book2 Books    /* Declare Book2 of type Book */

   /* book 1 specification */
   Book1.title = "Go Programming"
   Book1.author = "Mahesh Kumar"
   Book1.subject = "Go Programming Tutorial"
   Book1.book_id = 6495407

   /* book 2 specification */
   Book2.title = "Telecom Billing"
   Book2.author = "Zara Ali"
   Book2.subject = "Telecom Billing Tutorial"
   Book2.book_id = 6495700

   /* print Book1 info */
   printBook(Book1)

   /* print Book2 info */
   printBook(Book2)
}
func printBook( book Books ) {
   fmt.Printf( "Book title : %s\n", book.title);
   fmt.Printf( "Book author : %s\n", book.author);
   fmt.Printf( "Book subject : %s\n", book.subject);
   fmt.Printf( "Book book_id : %d\n", book.book_id);
}

再比如结合分水岭中的指针,对Struct进行指针操作:

代码语言:javascript
复制
package main

import "fmt"

type Books struct {
   title string
   author string
   subject string
   book_id int
}
func main() {
   var Book1 Books   /* Declare Book1 of type Book */
   var Book2 Books   /* Declare Book2 of type Book */

   /* book 1 specification */
   Book1.title = "Go Programming"
   Book1.author = "Mahesh Kumar"
   Book1.subject = "Go Programming Tutorial"
   Book1.book_id = 6495407

   /* book 2 specification */
   Book2.title = "Telecom Billing"
   Book2.author = "Zara Ali"
   Book2.subject = "Telecom Billing Tutorial"
   Book2.book_id = 6495700

   /* print Book1 info */
   printBook(&Book1)

   /* print Book2 info */
   printBook(&Book2)
}
func printBook( book *Books ) {
   fmt.Printf( "Book title : %s\n", book.title);
   fmt.Printf( "Book author : %s\n", book.author);
   fmt.Printf( "Book subject : %s\n", book.subject);
   fmt.Printf( "Book book_id : %d\n", book.book_id);
}

如果猜的不错,你肯定是鼠标快速划过就完事了。 别走神,里面真有彩蛋。为啥提出这两个例子,是因为具体实践中,这是经常大意犯的错误。先看这两个例子的区别:

代码语言:javascript
复制
func printBook( book Books ) { ... }
func printBook( book *Books ) { ... }

一个是值传递,一个是引用传递。 因此在第一个例子中,如果printBook里面修改了数据,比如:

代码语言:javascript
复制
book.title = "lala"

外面仍然无法感知,因为是值传递。修改的是副本,不是本体。但如果在第二个例子中,修改了数据,外层就会收到影响,因为都是本体。

代码语言:javascript
复制
package main

import "fmt"

type Books struct {
    title   string
    author  string
    subject string
    book_id int
}

func main() {
    var Book1 Books /* Declare Book1 of type Book */
    var Book2 Books /* Declare Book2 of type Book */

    /* book 1 specification */
    Book1.title = "Go Programming"
    Book1.author = "Mahesh Kumar"
    Book1.subject = "Go Programming Tutorial"
    Book1.book_id = 6495407

    /* book 2 specification */
    Book2.title = "Telecom Billing"
    Book2.author = "Zara Ali"
    Book2.subject = "Telecom Billing Tutorial"
    Book2.book_id = 6495700

    /* print Book1 info */
    printBook(Book1)
    fmt.Println(Book1.title)
    /* print Book2 info */
    printBook(Book2)
}
func printBook(book Books) {
    book.title = "lala"
    fmt.Printf("Book title : %s\n", book.title);
    fmt.Printf("Book author : %s\n", book.author);
    fmt.Printf("Book subject : %s\n", book.subject);
    fmt.Printf("Book book_id : %d\n", book.book_id);
}

跑一下,看看结果就能看出区别了。

所以就这里需要注意一下,其它关于Struct的坑应该算是没有了吧。 如果有,恩,那就有吧。 坑坑何其多,岂能填的完。如果哪天我开公司,一定要招一个叫"田德湾"的员工,就冲着名字,吉利!

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2017-12-01 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档