ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

Go语言入门

2020-01-23 09:04:19  阅读:281  来源: 互联网

标签:语言 入门 deck fmt go func Go main string


因为做分布式相关项目需要接触go语言,本文是基于Udemy上的一门go基础课的笔记,主要是代码例子的形式来熟悉go的一些特性,比如struct, map, interface, Channels and Go Routines,适合接触过一些其他编程语言的同学来快速了解go。

Basic project : Card

首先以一个扑克牌的项目为例子来熟悉go的基本语法,涉及variable declaration, type conversion, receiver, slice, multiple return等知识。实现的是扑克中的newDeck(), deal(), shuffle()以及deckToFile()和FiletoDeck()功能。包含实现功能的deck.go文件,可执行的main.go文件,以及用来测试的deck_test.go文件。

Package :executable package & reusable package
package main --> executable package (means go build can make a main.exe)

deck.go

package main

import (
	"fmt"
	"io/ioutil"
	"math/rand"
	"os"
	"strings"
	"time"
)

// Create a new type of "deck"
// which is a slice of strings
type deck []string

func (d deck) print() {
	for i, card := range d {
		fmt.Println(i, card)
	}
}

func newDeck() deck {
	cards := deck{}

	cardSuits := []string{"Spades", "Diamonds", "Hearts", "Clubs"}
	cardValues := []string{"Ace", "Two", "Three", "Four"}

	for _, suit := range cardSuits {
		for _, value := range cardValues {
			cards = append(cards, value+" of "+suit)
		}
	}

	return cards
}

func deal(d deck, handSize int) (deck, deck) {
	return d[:handSize], d[handSize:]
}

func (d deck) toString() string {
	return strings.Join([]string(d), ",")
}

func (d deck) saveToFile(filename string) error {
	return ioutil.WriteFile(filename, []byte(d.toString()), 0666)
}

func newDeckFromfile(filename string) deck {
	bs, err := ioutil.ReadFile(filename)
	if err != nil {
		fmt.Println("Error:", err)
		os.Exit(1)
	}
	s := strings.Split(string(bs), ",")
	return deck(s)
}

func (d deck) shuffle() {
	source := rand.NewSource(time.Now().UnixNano())
	r := rand.New(source)
	for i := range d {
		newPosition := r.Intn(len(d) - 1)
		d[i], d[newPosition] = d[newPosition], d[i]
	}
}

main.go

package main

import "fmt"

func main() {
	cards := newDeck()
	cards.saveToFile("my_cards")
	fmt.Println(cards.toString())
	hand, remainingCards := deal(cards, 5)
	hand.print()
	remainingCards.print()
	newCards := newDeckFromfile("my_cards")
	fmt.Println("new cards:", newCards.toString())
	newCards.shuffle()
	fmt.Println("shuffled new cards:", newCards.toString())
}

deck_test.go

package main

import (
	"os"
	"testing"
)

func TestNewDeck(t *testing.T) {
	d := newDeck()
	if len(d) != 16 {
		t.Errorf("Expected deck length of 16, but got %v", len(d))
	}

	if d[0] != "Ace of Spades" {
		t.Errorf("Wrong first card")
	}

	if d[len(d)-1] != "Four of Clubs" {
		t.Errorf("Wrong last card")
	}
}

func TestSaveToDeckAndNewDeckTestFromFile(t *testing.T) {
	os.Remove("_decktesting")

	d := newDeck()
	d.saveToFile("_decktesting")

	loadedDeck := newDeckFromfile("_decktesting")

	if len(loadedDeck) != 16 {
		t.Errorf("Expected 16 cards in deck, got %v", len(loadedDeck))
	}
	os.Remove("_decktesting")
}

Struct

以一个person type为例子,熟悉struct。注意struct是pass by value的,所以要想改变原来的对象,需要以指针为receiver。

package main

import "fmt"

type contactInfo struct {
	email   string
	zipCode int
}

type person struct {
	firstName string
	lastName  string
	contactInfo
}

func main() {
	// Create a person object
	var tom person
	tom.firstName = "Tom"
	tom.lastName = "Anderson"
	// Another way to create a person with initialization
	jim := person{
		firstName: "Jim",
		lastName:  "Party",
		contactInfo: contactInfo{
			email:   "jin@gmail.com",
			zipCode: 9400,
		},
	}
	// Update value inside the object
	jim.updateName("jimmy")
	// function use struct person as receiver
	jim.print()
}

func (p person) print() {
	fmt.Printf("%+v", p)
}
// Need to use pointers, directly, structs are pass by value
func (p *person) updateName(newFirstName string) {
	(*p).firstName = newFirstName
}

Map

map有点类似于Python里面的dict。用于函数时传的是地址,可以直接对原来的map修改。概念不难理解,主要是了解以下语法怎么写。

package main

import "fmt"

func main() {
	//create a map
	colors := map[string]string{
		"red":   "#ff0000",
		"green": "#4bf745",
	}
	fmt.Println(colors)
	//another way to initialize
	colors2 := make(map[string]string)
	colors2["white"] = "#ffffff"
	//delete
	map3 := make(map[int]string)
	map3[10] = "lalalala"
	fmt.Println(map3)
	delete(map3, 10)
	fmt.Println(map3)
	//iterate map
	printMap(colors2)
}

func printMap(c map[string]string) {
	for color, hex := range c {
		fmt.Println("Hex code for", color, "is", hex)
	}
}

Interface

interface这个概念在很多编程语言中都有出现。与其他语言一样go里面的interface类型helps reuse code, 不可以用来直接实例化对象。go interfaces are “implicit”,不像Java需要去继承实现一个interface那种manually say this type satisfy certain interface, 以下代码为例,就是有getGreeting()方法的type就自动可以属于bot 。另外go里面没有generic type的概念。

package main

import "fmt"

//Cannot directly create a value out of an interface type
type bot interface {
	getGreeting() string
}

type englishBot struct{}
type spanishBot struct{}

func main() {
	eb := englishBot{}
	sb := spanishBot{}
	printGreeting(eb)
	printGreeting(sb)
}
func printGreeting(b bot) {
	fmt.Println(b.getGreeting())
}

func (eb englishBot) getGreeting() string {
	return "Hi, there!"
}

func (sb spanishBot) getGreeting() string {
	return "Halo"
}

interface可以嵌套

Another small example to understand interface (learn to read documents)
Main purpose of the project is getting and logging response of http request.
Need to go through go documents and learn about Reader interface and Writer interface

package main

import (
	"fmt"
	"io"
	"net/http"
	"os"
)

type logWriter struct{}

func main() {
	resp, err := http.Get("http://google.com")
	if err != nil {
		fmt.Println("Error:", err)
		os.Exit(1)
	}
	// initialize an empty byte slice with 99999 elements
	b := make([]byte, 99999)
	resp.Body.Read(b)
	fmt.Println(string(b))
	// better way to do the same thing
	io.Copy(os.Stdout, resp.Body)
	// use own custom writer
	lw := logWriter{}
	io.Copy(lw, resp.Body)
}

func (logWriter) Write(bs []byte) (int, error) {
	fmt.Println(string(bs))
	fmt.Println("Just wrote this many bytes:", len(bs))
	return len(bs), nil
}

Channels and Go Routines

Sequence check link
slow: fetch one, complete one, move to next one

package main

import (
	"fmt"
	"net/http"
)

func main() {
	links := []string{
		"http://google.com",
		"http://facebook.com",
		"http://stackoverflow.com",
		"http://golang.org",
		"http://amazon.com",
	}
	for _, link := range links {
		checkLink(link)
	}
}

func checkLink(link string) {
	_, err := http.Get(link)
	if err != nil {
		fmt.Println(link, "might be down!")
		return
	}
	fmt.Println(link, "is up!")
}

Parallel way: Channels and Go Routines

package main

import (
	"fmt"
	"net/http"
	"time"
)

func main() {
	links := []string{
		"http://google.com",
		"http://facebook.com",
		"http://stackoverflow.com",
		"http://golang.org",
		"http://amazon.com",
	}

	c := make(chan string)

	for _, link := range links {
		go checkLink(link, c)
	}

	for l := range c {
		go func(link string) {
			time.Sleep(5 * time.Second)
			checkLink(link, c)
		}(l)
	}

}

func checkLink(link string, c chan string) {
	_, err := http.Get(link)
	if err != nil {
		fmt.Println(link, "might be down!")
		c <- link
		return
	}
	fmt.Println(link, "is up!")
	c <- link
}

Yichen � 发布了1 篇原创文章 · 获赞 0 · 访问量 22 私信 关注

标签:语言,入门,deck,fmt,go,func,Go,main,string
来源: https://blog.csdn.net/yichenl2/article/details/104073359

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有