• Go面向对象篇


    结构体、方法、扩展已有类型、GOPAT和以及目录结构

    前言

    Go语言不是纯面向对象的编程语言,Go的面向对象中,接口体替代了类。

    Go没提供类class,其提供struct结构体,method方法可在结构体上添加,提供捆绑数据和方法的行为与类类似。

    Go不支持构造函数,提供NewT(parameters)函数初始化类型T和所需的值,若包只定义一个类型命名为 New(parameters) 

    组成Composition替代继承Inheritance,通过嵌入结构体实现(将一个struct类型嵌入到另一个结构中实现)

    Go利用接口帮助实现多态性,因为Go中接口可隐式实现,若类型为接口声明中所有方法提供了定义,则实现了一个接口。

    结构体

    特点:只支持封装、不支持继承和多态(其余用面向接口编程实现) 故Go无class只有struct

    定义

    type struct_variable_type struct {
       member definition;
       member definition;
       ...
       member definition;
    }

    使用: variable_name := structure_variable_type {value1, value2...valuen} 

    初始化

     P := person{"Tom", 25}  按照顺序提供初始值

     P := person{age:24, name:"Tom"} 通过field:value方式初始化

     p := new(person)然后初始化p.age=24 new方式如果未设置初始值会赋予类型的默认初始值

    访问:

    通过点.操作符用于访问结构的各个字段。例子: Book1.title = "Go 语言" 

    注意:

    type Books struct {
    }
    
    func (s Books) String() string {
        return "data"
    }
    func main() {
        fmt.Printf("%v
    ", Books{})
    }

    结构体指针

    指针指向一个结构体 也可以创建指向结构的指针。

    结构体指针: var struct_pointer *Books 以此定义的指针变量可以存储结构体变量的地址。

    查看结构体变量地址,可以将 & 符号放置于结构体变量前,例子: struct_pointer = &Book1; 

    使用结构体指针访问结构体成员,使用.操作符: struct_pointer.title; 

    结构体匿名字段

    匿名字段:用字段来创建数据结构,这些字段只包含一个没有字段名的类型,称为匿名字段。

    例子:

    type Human struct {
        name string
        age int
        weight int
    }
    type Student struct {
        Human // 匿名字段,那么默认Student就包含了Human的所有字段
        speciality string
    }
    使用:
     mark := Student{Human{"Mark", 25, 120}, "Computer Science"}

    方法

    Go中同时有函数和方法,一个方法就是一个包含了接收者的函数,接收者可以是命名类型或者结构体类型的一个值或者一个指针,所有给定类型的方法属于该类型的方法集。

    概念:只是一个函数,带有一个特殊接收器类型,接收器可以是struct类型或非struct类型,接收方可在内部访问。

    语法

    定义 

    func (t Type) methodName(parameter list) {
    }

    例子

    type Employee struct {
        name     string
        salary   int
        currency string
    }
    
    /*
     displaySalary() method has Employee as the receiver type
    */
    func (e Employee) displaySalary() {
        fmt.Printf("Salary of %s is %s%d", e.name, e.currency, e.salary)
    }
    使用
     emp1.displaySalary() //Calling displaySalary() method of Employee type

    特点

    可定义相同的方法名,但接收者不同,方法就不同。

    方法里可以访问接受者的字段。调用方法通过.访问,类似struct里访问字段一样。

    存在意义

    Go不支持类,不是存粹面向对象语言,类型的方法其实就是一种实现类似于类的行为的方法。

    之所以有函数还需要方法,有一点则是相同名称的方法可在不同类型上定义,但具有相同名称的函数是不允许的。

    方法可以继承和重写的,存在继承关系时,按照就近原则,进行调用。

    本节重点

    1)GO安装路径为为GOROOT  如何设置GOPATH  在PATH中添加GOPATH/bin目录

    2)GOPATH目录(这里为/home/admin/go)下有三个文件夹bin  pkg  src但是一般是src是我自己创建,其余不是

    如果非要创建这几个文件夹,比如创建了pkg就涉及到IDEA中go run 时候可能go install会被拒绝写入由我自己创建的pkg

    3)IDEA工程保存路径(这里为 /home/admin/go/src/learngo)我自己注意:最好下次保存为 /home/admin/go/src/ycx/learngo

    4)无法直接获取golang的包因此使用工作gopm(获取时候采用go get命令 但是一定要记得安装了git)

    5)IDEA中运行某个程序时候如果报错(请自行查看是否到该包目录下go install了,如果没有会报错关于linux_amd64的)

    6)GPATH下:go build来编译  go install产生pkg文件和可执行文件  go run直接编译运行

     GOPATH

    [admin@localhost ~]$ cd /opt/go
    [admin@localhost go]$ pwd
    /opt/go
    [admin@localhost go]$ echo $GOPATH
    /home/admin/go
    [admin@localhost go]$ gedit /etc/profile

    GOPATH

    重点关注:GOPATH以及设置PATH关于GOPATH的

    go get

    在配置的GOPATH目录下执行命令:go get -v github.com/gpmgo/gopm 

    注意1:如果不能执行请查看自己是否安装了git

    注意:如果出现错误提示如下(请将src目录下的github.com文件夹删除使用命令为:rm -rf  文件夹名字

     安装gopm完毕查看目录下一些文件:(此时说明gopm安装完毕,可以通过查看gopm的help来运行了)

    [root@localhost go]# gopm help

    [root@localhost go]# gopm help get

    使用gopm

    使用一下命令第一次不会出现一下问题

     

    打开IDEA可以查看GOPATH已经出现:

    运行go build命令来build需要的goimports将其装在bin目录下面去

    注:这里它会做两件事情(第一件:将IDEA里的import两个空行 第二件:是在golang.org 的x目录下多很多东西)

    使用示例

    我们可以来使用一下:使用intsets.Sparse{}   下面是tree的总代码

    注意:运行程序treeentry.go运行程序出错:(这是由于自己认为创建了pkg,如果不是则不会报这个错误)

    解决办法:

     tree

    目录结构:

    package main
    
    import (
        "fmt"
    
        "learngo/tree"
    
        "golang.org/x/tools/container/intsets"
    )
    
    type myTreeNode struct {
        node *tree.Node
    }
    
    func (myNode *myTreeNode) postOrder() {
        if myNode == nil || myNode.node == nil {
            return
        }
    
        left := myTreeNode{myNode.node.Left}
        right := myTreeNode{myNode.node.Right}
    
        left.postOrder()
        right.postOrder()
        myNode.node.Print()
    }
    
    func testSparse() {
        s := intsets.Sparse{}
    
        s.Insert(1)
        s.Insert(1000)
        s.Insert(1000000)
        fmt.Println(s.Has(1000))
        fmt.Println(s.Has(10000000))
    }
    
    func main() {
        var root tree.Node
    
        root = tree.Node{Value: 3}
        root.Left = &tree.Node{}
        root.Right = &tree.Node{5, nil, nil}
        root.Right.Left = new(tree.Node)
        root.Left.Right = tree.CreateNode(2)
        root.Right.Left.SetValue(4)
    
        fmt.Print("In-order traversal: ")
        root.Traverse()
    
        fmt.Print("My own post-order traversal: ")
        myRoot := myTreeNode{&root}
        myRoot.postOrder()
        fmt.Println()
    
        nodeCount := 0
        root.TraverseFunc(func(node *tree.Node) {
            nodeCount++
        })
        fmt.Println("Node count:", nodeCount)
    
        c := root.TraverseWithChannel()
        maxNodeValue := 0
        for node := range c {
            if node.Value > maxNodeValue {
                maxNodeValue = node.Value
            }
        }
        fmt.Println("Max node value:", maxNodeValue)
    
        testSparse()
    }
    entry.go
    package tree
    
    import "fmt"
    
    type Node struct {
        Value       int
        Left, Right *Node
    }
    
    func (node Node) Print() {
        fmt.Print(node.Value, " ")
    }
    
    func (node *Node) SetValue(value int) {
        if node == nil {
            fmt.Println("Setting Value to nil " +
                "node. Ignored.")
            return
        }
        node.Value = value
    }
    
    func CreateNode(value int) *Node {
        return &Node{Value: value}
    }
    node.go
    package tree
    
    import "fmt"
    
    func (node *Node) Traverse() {
        node.TraverseFunc(func(n *Node) {
            n.Print()
        })
        fmt.Println()
    }
    
    func (node *Node) TraverseFunc(f func(*Node)) {
        if node == nil {
            return
        }
    
        node.Left.TraverseFunc(f)
        f(node)
        node.Right.TraverseFunc(f)
    }
    
    func (node *Node) TraverseWithChannel() chan *Node {
        out := make(chan *Node)
        go func() {
            node.TraverseFunc(func(node *Node) {
                out <- node
            })
            close(out)
        }()
        return out
    }
    traversal.go

    输出是:

    In-order traversal: 0 2 3 4 5 
    My own post-order traversal: 2 0 4 5 3 
    Node count: 5
    Max node value: 5
    true
    false
    
    Process finished with exit code 0

     queue

    先做准备工作

    代码结构如下:

    package main
    
    import (
        "fmt"
        "learngo/queue"
    )
    
    func main() {
        q := queue.Queue{1}
    
        q.Push(2)
        q.Push(3)
        fmt.Println(q.Pop())
        fmt.Println(q.Pop())
        fmt.Println(q.IsEmpty())
        fmt.Println(q.Pop())
        fmt.Println(q.IsEmpty())
    }
    main.go
    package queue
    
    // A FIFO queue.
    type Queue []int
    
    // Pushes the element into the queue.
    //         e.g. q.Push(123)
    func (q *Queue) Push(v int) {
        *q = append(*q, v)
    }
    
    // Pops element from head.
    func (q *Queue) Pop() int {
        head := (*q)[0]
        *q = (*q)[1:]
        return head
    }
    
    // Returns if the queue is empty or not.
    func (q *Queue) IsEmpty() bool {
        return len(*q) == 0
    }
    queue.go

     输出是:

    1
    2
    false
    3
    true
    
    Process finished with exit code 0
    package queue
    
    import "fmt"
    
    func ExampleQueue_Pop() {
        q := Queue{1}
        q.Push(2)
        q.Push(3)
        fmt.Println(q.Pop())
        fmt.Println(q.Pop())
        fmt.Println(q.IsEmpty())
    
        fmt.Println(q.Pop())
        fmt.Println(q.IsEmpty())
    
        // Output:
        // 1
        // 2
        // false
        // 3
        // true
    }
    queue_test.go

     运行是:

     

  • 相关阅读:
    [leetcode ]429. N-ary Tree Level Order Traversale (easy)
    [leetcode] 559. Maximum Depth of N-ary Tree (easy)
    [leetcode] 406. Queue Reconstruction by Height (medium)
    [leetcode] 238. Product of Array Except Self (medium)
    [leetcode] 94. Binary Tree Inorder Traversal
    [leetcode] 621. Task Scheduler(medium)
    [leetcode] 309. Best Time to Buy and Sell Stock with Cooldown(medium)
    为窗口设置图标
    关闭住主窗口
    窗口居中显示
  • 原文地址:https://www.cnblogs.com/ycx95/p/9361122.html
Copyright © 2020-2023  润新知