golang 简单的可控循环

cycle.go
package main

import (
	"git.ll-games.com/backend/core/helpers"

	"context"
	"fmt"
	"time"
)

const (
	updateTimeout   = time.Millisecond * 500
	scoreSyncSecond = 100
)

type (
	runner struct {
		run     chan struct{}
		started bool
		ctx     context.Context
		cancel  context.CancelFunc
	}
)

func New() *runner {
	ctx, cancel := context.WithCancel(context.Background())
	return &runner{
		run:     make(chan struct{}, 1),
		started: false,
		ctx:     ctx,
		cancel:  cancel,
	}
}

func (r *runner) update(counter int) (done bool) {
	if counter == 10 {
		r.started = false
		return true
	}
	return false
}

func (r *runner) Start() {
	if r.started {
		return
	}
	r.started = true
	r.run <- struct{}{}
}

func (r *runner) Stop() {
	if !r.started {
		return
	}
	r.started = false
}

func (r *runner) Close() {
	close(r.run)
	r.cancel()
}

// run async
func (r *runner) Run() {
	defer println("close cycle")
	// из этого цикла выход только по close(c.run)
	for range r.run {
		var counter int
		println("run update cycle")
		for {
			if helpers.ContextDone(r.ctx) {
				return
			}
			if !r.started {
				println("stop cycle")
				break
			}
			counter++

			println(counter)

			done := r.update(counter)
			if done {
				break
			}
			time.Sleep(updateTimeout)
			if counter%scoreSyncSecond == 0 {
				counter = 0
			}
		}
	}
}

func main() {
	r := New()

	go r.Run()

	for {
		var input string
		_, _ = fmt.Scanln(&input)
		switch input {
		case "s":
			r.Start()
		case "p":
			r.Stop()
		case "c":
			r.Close()
			break
		}
	}
}

golang golang恐慌

panic.go
defer func() {
        if r := recover(); r != nil {
            fmt.Println("Recovered in f", r)
        }
    }()

golang [xml] xml解析与创建

[xml] xml解析与创建

1_xml_creating_marshal.go
package main

import (
	"encoding/xml"
	"fmt"
	"io/ioutil"
)

type Post struct {
	XMLName xml.Name `xml:"post"`
	Id      string   `xml:"id,attr"`
	Content string   `xml:"content"`
	Author  Author   `xml:"author"`
}

type Author struct {
	Id   string `xml:"id,attr"`
	Name string `xml:",chardata"`
}

func main() {
	post := Post{
		Id:      "1",
		Content: "Hello World!",
		Author: Author{
			Id:   "2",
			Name: "Sau Sheong",
		},
	}
  // output, err := xml.Marshal(&post)
  output, err := xml.MarshalIndent(&post, "", "\t\t")
	if err != nil {
		fmt.Println("Error marshalling to XML:", err)
		return
	}
	err = ioutil.WriteFile("post.xml", []byte(xml.Header + string(output)), 0644)
	if err != nil {
		fmt.Println("Error writing XML to file:", err)
		return
	}
}

/*
<?xml version="1.0" encoding="UTF-8"?>
<post id="1">
		<content>Hello World!</content>
		<author id="2">Sau Sheong</author>
</post>
*/
2_xml_creating_encoder.go
package main

import (
	"encoding/xml"
	"fmt"
	"os"
)

type Post struct {
	XMLName xml.Name `xml:"post"`
	Id      string   `xml:"id,attr"`
	Content string   `xml:"content"`
	Author  Author   `xml:"author"`
}

type Author struct {
	Id   string `xml:"id,attr"`
	Name string `xml:",chardata"`
}

func main() {
	post := Post{
		Id:      "1",
		Content: "Hello World!",
		Author: Author{
			Id:   "2",
			Name: "Sau Sheong",
		},
	}

	xmlFile, err := os.Create("post.xml")
	if err != nil {
		fmt.Println("Error creating XML file:", err)
		return
	}
	encoder := xml.NewEncoder(xmlFile)
	encoder.Indent("", "\t")
	err = encoder.Encode(&post)
	if err != nil {
		fmt.Println("Error encoding XML to file:", err)
		return
	}
}

/*
<?xml version="1.0" encoding="UTF-8"?>
<post id="1">
		<content>Hello World!</content>
		<author id="2">Sau Sheong</author>
</post>
*/
3_xml_parsing_unmarshal.go
package main

import (
	"encoding/xml"
	"fmt"
	"io/ioutil"
	"os"
)

type Post struct {
	XMLName  xml.Name  `xml:"post"`
	Id       string    `xml:"id,attr"`
	Content  string    `xml:"content"`
	Author   Author    `xml:"author"`
	Xml      string    `xml:",innerxml"`
	Comments []Comment `xml:"comments>comment"`
}

type Author struct {
	Id   string `xml:"id,attr"`
	Name string `xml:",chardata"`
}

type Comment struct {
	Id      string `xml:"id,attr"`
	Content string `xml:"content"`
	Author  Author `xml:"author"`
}

func main() {
	xmlFile, err := os.Open("post.xml")
	if err != nil {
		fmt.Println("Error opening XML file:", err)
		return
	}
	defer xmlFile.Close()
	xmlData, err := ioutil.ReadAll(xmlFile)
	if err != nil {
		fmt.Println("Error reading XML data:", err)
		return
	}

	var post Post
	xml.Unmarshal(xmlData, &post)
	fmt.Println(post)
}

/*
<?xml version="1.0" encoding="utf-8"?>
<post id="1">
  <content>Hello World!</content>
  <author id="2">Sau Sheong</author>
  <comments>
    <comment id="1">
      <content>Have a great day!</content>
      <author>Adam</author>
    </comment>
    <comment id="2">
      <content>How are you today?</content>
      <author>Betty</author>
    </comment>
  </comments>
</post>
*/
4_xml_parsing_decoder.go
package main

import (
	"encoding/xml"
	"fmt"
	"io"
	"os"
)

type Post struct {
	XMLName  xml.Name  `xml:"post"`
	Id       string    `xml:"id,attr"`
	Content  string    `xml:"content"`
	Author   Author    `xml:"author"`
	Xml      string    `xml:",innerxml"`
	Comments []Comment `xml:"comments>comment"`
}

type Author struct {
	Id   string `xml:"id,attr"`
	Name string `xml:",chardata"`
}

type Comment struct {
	Id      string `xml:"id,attr"`
	Content string `xml:"content"`
	Author  Author `xml:"author"`
}

func main() {
	xmlFile, err := os.Open("post.xml")
	if err != nil {
		fmt.Println("Error opening XML file:", err)
		return
	}
	defer xmlFile.Close()

	decoder := xml.NewDecoder(xmlFile)
	for {
		t, err := decoder.Token()
		if err == io.EOF {
			break
		}
		if err != nil {
			fmt.Println("Error decoding XML into tokens:", err)
			return
		}

		switch se := t.(type) {
		case xml.StartElement:
			if se.Name.Local == "comment" {
				var comment Comment
				decoder.DecodeElement(&comment, &se)
				fmt.Println(comment)
			}
		}
	}
}

/*
<?xml version="1.0" encoding="utf-8"?>
<post id="1">
  <content>Hello World!</content>
  <author id="2">Sau Sheong</author>
  <comments>
    <comment id="1">
      <content>Have a great day!</content>
      <author id="3">Adam</author>
    </comment>
    <comment id="2">
      <content>How are you today?</content>
      <author id="4">Betty</author>
    </comment>
  </comments>
</post>
*/

golang [Fibonacci] golang实现

[Fibonacci] golang实现

fibonacciIterative.go
// Iterative Fibonacci
func fibonacciIterative(n int) int {
    current, prev := 0, 1
    for i := 0; i < n; i++ {
        current, prev = current + prev, current
    }
    return current
}
fibonacciRecursive.go
// Recursive Fibonacci
func fibonacciRecursive(n int) int {
    if n < 2 {
        return n
    } 
    return fibonacciRecursive(n - 1) + fibonacciRecursive(n - 2)
}

golang [json] json解析与创建

[json] json解析与创建

1_json_creating_marshal.go
package main

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
)

type Post struct {
	Id       int       `json:"id"`
	Content  string    `json:"content"`
	Author   Author    `json:"author"`
	Comments []Comment `json:"comments"`
}

type Author struct {
	Id   int    `json:"id"`
	Name string `json:"name"`
}

type Comment struct {
	Id      int    `json:"id"`
	Content string `json:"content"`
	Author  string `json:"author"`
}

func main() {
	post := Post{
		Id:      1,
		Content: "Hello World!",
		Author: Author{
			Id:   2,
			Name: "Sau Sheong",
		},
		Comments: []Comment{
			Comment{
				Id:      1,
				Content: "Have a great day!",
				Author:  "Adam",
			},
			Comment{
				Id:      2,
				Content: "How are you today?",
				Author:  "Betty",
			},
		},
	}

	output, err := json.MarshalIndent(&post, "", "\t\t")
	if err != nil {
		fmt.Println("Error marshalling to JSON:", err)
		return
	}
	err = ioutil.WriteFile("post.json", output, 0644)
	if err != nil {
		fmt.Println("Error writing JSON to file:", err)
		return
	}
}
2_json_creating_encoder.go
package main

import (
	"encoding/json"
	"fmt"
	"io"
 	"os"
)

type Post struct {
	Id       int       `json:"id"`
	Content  string    `json:"content"`
	Author   Author    `json:"author"`
	Comments []Comment `json:"comments"`
}

type Author struct {
	Id   int    `json:"id"`
	Name string `json:"name"`
}

type Comment struct {
	Id      int    `json:"id"`
	Content string `json:"content"`
	Author  string `json:"author"`
}

func main() {
	post := Post{
		Id:      1,
		Content: "Hello World!",
		Author: Author{
			Id:   2,
			Name: "Sau Sheong",
		},
		Comments: []Comment{
			Comment{
				Id:      1,
				Content: "Have a great day!",
				Author:  "Adam",
			},
			Comment{
				Id:      2,
				Content: "How are you today?",
				Author:  "Betty",
			},
		},
	}

	jsonFile, err := os.Create("post.json")
	if err != nil {
		fmt.Println("Error creating JSON file:", err)
		return
	}
	jsonWriter := io.Writer(jsonFile)
	encoder := json.NewEncoder(jsonWriter)  
	err = encoder.Encode(&post)
	if err != nil {
		fmt.Println("Error encoding JSON to file:", err)
		return
	}
}
3_json_parsing_unmarshal.go
package main

import (
	"encoding/json"
	"fmt"
	"os"
    "io/ioutil"
)

type Post struct {
	Id       int       `json:"id"`
	Content  string    `json:"content"`
	Author   Author    `json:"author"`
	Comments []Comment `json:"comments"`
}

type Author struct {
	Id   int    `json:"id"`
	Name string `json:"name"`
}

type Comment struct {
	Id      int    `json:"id"`
	Content string `json:"content"`
	Author  string `json:"author"`
}

// decode JSON from file to struct
func unmarshal(filename string) (post Post, err error) {
	jsonFile, err := os.Open(filename)
	if err != nil {
		fmt.Println("Error opening JSON file:", err)
		return
	}
	defer jsonFile.Close()

	jsonData, err := ioutil.ReadAll(jsonFile)
	if err != nil {
		fmt.Println("Error reading JSON data:", err)
		return
	}
	json.Unmarshal(jsonData, &post)  
    return
}

func main() {
	post, err := unmarshal("post.json")
	if err != nil {
		fmt.Println("Error:", err)
	}
	fmt.Println("Post is", post)
}
4_json_parsing_decoder.go
package main

import (
	"encoding/json"
	"fmt"
	"os"
    "io/ioutil"
)

type Post struct {
	Id       int       `json:"id"`
	Content  string    `json:"content"`
	Author   Author    `json:"author"`
	Comments []Comment `json:"comments"`
}

type Author struct {
	Id   int    `json:"id"`
	Name string `json:"name"`
}

type Comment struct {
	Id      int    `json:"id"`
	Content string `json:"content"`
	Author  string `json:"author"`
}

// decode JSON from file to struct
func decode(filename string) (post Post, err error) {
	jsonFile, err := os.Open(filename)
	if err != nil {
		fmt.Println("Error opening JSON file:", err)
		return
	}
	defer jsonFile.Close()

	decoder := json.NewDecoder(jsonFile)
	err = decoder.Decode(&post)
	if err != nil {
		fmt.Println("Error decoding JSON:", err)
		return
	}
	return
}

func main() {
	post, err := decode("post.json")
	if err != nil {
		fmt.Println("Error:", err)
	}
	fmt.Println("Post is", post)
}

golang 测试

测试

1_test.go
//要测试的代码:
func Fib(n int) int {
    if n < 2 {
    	return n
    }
    return Fib(n-1) + Fib(n-1)
}


//测试代码:
func TestFib(t *testing.T) {
	var (
		in       = 7
		expected = 13
	)
	actual := Fib(in)
	if actual != expected {
		t.Errorf("Fib(%d) = %d; expected %d", in, actual, expected)
	}
}
2_TableDriven_test.go
//要测试的代码:
func Fib(n int) int {
    if n < 2 {
    	return n
    }
    return Fib(n-1) + Fib(n-1)
}


//测试代码:
func TestFib(t *testing.T) {
	var fibTests = []struct {
		in       int // input
		expected int // expected result
	}{
		{1, 1},
		{2, 1},
		{3, 2},
	}

	for _, tt := range fibTests {
		actual := Fib(tt.in)
		if actual != tt.expected {
			t.Errorf("Fib(%d) = %d; expected %d", tt.in, actual, tt.expected)
		}
	}
}
3_Parallel_test.go
//要测试的代码:
var (
	data   = make(map[string]string)
	locker sync.RWMutex
)

func WriteToMap(k, v string) {
	locker.Lock()
	defer locker.Unlock()
	data[k] = v
}

func ReadFromMap(k string) string {
	locker.RLock()
	defer locker.RUnlock()
	return data[k]
}


//测试代码:
//go test -v -parallel 2
var pairs = []struct {
	k string
	v string
}{
	{"polaris", " 徐新华 "},
	{"studygolang", "Go 语言中文网 "},
	{"stdlib", "Go 语言标准库 "},
	{"polaris1", " 徐新华 1"},
	{"studygolang1", "Go 语言中文网 1"},
	{"stdlib1", "Go 语言标准库 1"},
}

// 注意 TestWriteToMap 需要在 TestReadFromMap 之前
func TestWriteToMap(t *testing.T) {
	t.Parallel()
	for _, tt := range pairs {
		WriteToMap(tt.k, tt.v)
	}
}

func TestReadFromMap(t *testing.T) {
	t.Parallel()
	for _, tt := range pairs {
		actual := ReadFromMap(tt.k)
		if actual != tt.v {
			t.Errorf("the value of key(%s) is %s, expected: %s", tt.k, actual, tt.v)
		}
	}
}
4_Benchmark_test.go
//要测试的代码:
func Fib(n int) int {
    if n < 2 {
    	return n
    }
    return Fib(n-1) + Fib(n-1)
}


//测试了 Fib(10) 的情况
func BenchmarkFib10(b *testing.B) {
    for n := 0; n < b.N; n++ {
    	Fib(10)
    }
}

//测试更多不同的情况
//go test -bench=.
func BenchmarkFib1(b *testing.B)  { benchmarkFib(1, b) }
func BenchmarkFib2(b *testing.B)  { benchmarkFib(2, b) }
func BenchmarkFib3(b *testing.B)  { benchmarkFib(3, b) }
func BenchmarkFib10(b *testing.B) { benchmarkFib(10, b) }
func BenchmarkFib20(b *testing.B) { benchmarkFib(20, b) }
func BenchmarkFib40(b *testing.B) { benchmarkFib(40, b) }

func benchmarkFib(i int, b *testing.B) {
	for n := 0; n < b.N; n++ {
		Fib(i)
	}
}
5_TestMain_test.go
package mytestmain

import (  
	"flag"
	"fmt"
	"os"
	"testing"
)

var db struct {  
	Dns string
}

func TestMain(m *testing.M) {
	db.Dns = os.Getenv("DATABASE_DNS")
	if db.Dns == "" {
		db.Dns = "root:123456@tcp(localhost:3306)/?charset=utf8&parseTime=True&loc=Local"
	}

	flag.Parse()
	exitCode := m.Run()

	db.Dns = ""

	// 退出
	os.Exit(exitCode)
}

func TestDatabase(t *testing.T) {
	fmt.Println(db.Dns)
}
6_Http_test.go
//https://github.com/polaris1119/The-Golang-Standard-Library-by-Example/blob/master/chapter09/09.6.md
package main

import (
	"encoding/json"
	"net/http"
	"net/http/httptest"
	"os"
	"strings"
	"testing"
)

var mux *http.ServeMux
var writer *httptest.ResponseRecorder

func TestMain(m *testing.M) {
	setUp()
	code := m.Run()
	tearDown()
	os.Exit(code)
}

func setUp() {
	mux = http.NewServeMux()	//创建多路复用器
	mux.HandleFunc("/post/", handleRequest)	//多路复用器与被测试的处理器进行绑定
	writer = httptest.NewRecorder()	//创建记录器
}

func tearDown() {
}

func TestHandleGet(t *testing.T) {
	request, _ := http.NewRequest("GET", "/post/1", nil)	//创建请求
	mux.ServeHTTP(writer, request)	//向被测处理器发送请求,引发对记录器的写入操作

	if writer.Code != 200 {	//对记录器记载的相应结果进行检查
		t.Errorf("Response code is %v", writer.Code)
	}
	var post Post
	json.Unmarshal(writer.Body.Bytes(), &post)
	if post.Id != 1 {
		t.Errorf("Cannot retrieve JSON post")
	}
}

func TestHandlePut(t *testing.T) {
	json := strings.NewReader(`{"content":"Updated post","author":"Sau Sheong"}`)
	request, _ := http.NewRequest("PUT", "/post/1", json)
	mux.ServeHTTP(writer, request)

	if writer.Code != 200 {
		t.Errorf("Response code is %v", writer.Code)
	}
}
7_Skip_test.go
//用t.Skip
func TestXxx(t *testing.T) {
	t.Skip("Skipping")
}

//传入-short标志
//go test -v -cover -short
func TestXxx(t *testing.T){
  	if testing.Short() {
        t.Skip("Skipping")
  	}
}

golang Go中的简单HTTP服务器使用mongoDB和通道

Go中的简单HTTP服务器使用mongoDB和通道

server.go
package main

import (
	"encoding/json"
	"fmt"
	"gopkg.in/mgo.v2"
	"gopkg.in/mgo.v2/bson"
	"io"
	"math/rand"
	"net/http"
	"sync"
	"time"
)

// handler functions

// simple handler that just responds with a fixed string
func requestHandler1(w http.ResponseWriter, r *http.Request) {
	io.WriteString(w, "Hello world!")
}

// Handler which makes three mongo queries at the same time and responds with the 
// one that returns the quickest
func requestHandler2(w http.ResponseWriter, r *http.Request, mongoSession *mgo.Session) {
	c1 := make(chan string)
	c2 := make(chan string)
	c3 := make(chan string)

	go query("AAPL", mongoSession, c1)
	go query("GOOG", mongoSession, c2)
	go query("MSFT", mongoSession, c3)

	select {
	case data := <-c1:
		io.WriteString(w, data)
	case data := <-c2:
		io.WriteString(w, data)
	case data := <-c3:
		io.WriteString(w, data)
	}

}

// runs a query against mongodb
func query(ticker string, mongoSession *mgo.Session, c chan string) {
	sessionCopy := mongoSession.Copy()
	defer sessionCopy.Close()
	collection := sessionCopy.DB("akka").C("stocks")
	var result bson.M
	collection.Find(bson.M{"Ticker": ticker}).One(&result)

	asString, _ := json.MarshalIndent(result, "", "  ")

	amt := time.Duration(rand.Intn(120))
	time.Sleep(time.Millisecond * amt)
	c <- string(asString)
}

// starts the application
func main() {

	server := http.Server{
		Addr:    ":8000",
		Handler: NewHandler(),
	}

	// start listening
	fmt.Println("Started server 2")
	server.ListenAndServe()

}

// Constructor for the server handlers
func NewHandler() *myHandler {
	h := new(myHandler)
	h.defineMappings()

	return h
}

// Definition of this struct
type myHandler struct {
	// holds the mapping
	mux map[string]func(http.ResponseWriter, *http.Request)
}

// functions defined on struct
func (my *myHandler) defineMappings() {

	session, err := mgo.Dial("localhost")
	if err != nil {
		panic(err)
	}

	// make the mux
	my.mux = make(map[string]func(http.ResponseWriter, *http.Request))

	// matching of request path
	my.mux["/hello"] = requestHandler1
	my.mux["/get"] = my.wrap(requestHandler2, session)
}

// returns a function so that we can use the normal mux functionality and pass in a shared mongo session
func (my *myHandler) wrap(target func(http.ResponseWriter, *http.Request, *mgo.Session), mongoSession *mgo.Session) func(http.ResponseWriter, *http.Request) {
	return func(resp http.ResponseWriter, req *http.Request) {
		target(resp, req, mongoSession)
	}
}

// implements serveHTTP so this struct can act as a http server
func (my *myHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	if h, ok := my.mux[r.URL.String()]; ok {
		// handle paths that are found
		h(w, r)
		return
	} else {
		// handle unhandled paths
		io.WriteString(w, "My server: "+r.URL.String())
	}
}

golang 将CRD与动态go客户端一起使用的示例

将CRD与动态go客户端一起使用的示例

dynamic_crds.go
package main

import (
	"fmt"
	"log"
	"os/user"
	"path/filepath"
	"strings"

	apixv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1"
	apixv1beta1client "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/typed/apiextensions/v1beta1"
	"k8s.io/apimachinery/pkg/api/errors"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
	"k8s.io/apimachinery/pkg/runtime/schema"
	"k8s.io/client-go/dynamic"
	"k8s.io/client-go/rest"
	"k8s.io/client-go/tools/clientcmd"

	_ "k8s.io/client-go/plugin/pkg/client/auth/gcp"
)

var (
	runtimeClassGVR = schema.GroupVersionResource{
		Group:    "node.k8s.io",
		Version:  "v1alpha1",
		Resource: "runtimeclasses",
	}
)

func main() {
	log.Print("Loading client config")
	config, err := clientcmd.BuildConfigFromFlags("", userConfig())
	errExit("Failed to load client conifg", err)

	log.Print("Loading dynamic client")
	client, err := dynamic.NewForConfig(config)
	errExit("Failed to create client", err)

	RegisterRuntimeClassCRD(config)
	CreateSampleRuntimeClasses(client)
	PrintRuntimeHandlers(client)
}

func RegisterRuntimeClassCRD(config *rest.Config) {
	apixClient, err := apixv1beta1client.NewForConfig(config)
	errExit("Failed to load apiextensions client", err)

	crds := apixClient.CustomResourceDefinitions()

	const (
		dns1123LabelFmt        string = "[a-z0-9]([-a-z0-9]*[a-z0-9])?"
		dns1123SubdomainFmt    string = dns1123LabelFmt + "(\\." + dns1123LabelFmt + ")*"
		dns1123SubdomainRegexp string = "^" + dns1123SubdomainFmt + "$"
	)
	runtimeClassCRD := &apixv1beta1.CustomResourceDefinition{
		ObjectMeta: metav1.ObjectMeta{
			Name: "runtimeclasses.node.k8s.io",
		},
		Spec: apixv1beta1.CustomResourceDefinitionSpec{
			Group:   "node.k8s.io",
			Version: "v1alpha1",
			Versions: []apixv1beta1.CustomResourceDefinitionVersion{{
				Name:    "v1alpha1",
				Served:  true,
				Storage: true,
			}},
			Names: apixv1beta1.CustomResourceDefinitionNames{
				Plural:   "runtimeclasses",
				Singular: "runtimeclass",
				Kind:     "RuntimeClass",
			},
			Scope: apixv1beta1.ClusterScoped,
			Validation: &apixv1beta1.CustomResourceValidation{
				OpenAPIV3Schema: &apixv1beta1.JSONSchemaProps{
					Properties: map[string]apixv1beta1.JSONSchemaProps{
						"spec": {
							Properties: map[string]apixv1beta1.JSONSchemaProps{
								"runtimeHandler": {
									Type:    "string",
									Pattern: dns1123SubdomainRegexp,
								},
							},
						},
					},
				},
			},
		},
	}
	log.Print("Registering RuntimeClass CRD")
	_, err = crds.Create(runtimeClassCRD)
	if err != nil {
		if errors.IsAlreadyExists(err) {
			log.Print("RuntimeClass CRD already registered")
		} else {
			errExit("Failed to create RuntimeClass CRD", err)
		}
	}
}

func CreateSampleRuntimeClasses(client dynamic.Interface) {
	res := client.Resource(runtimeClassGVR)

	rcs := map[string]string{
		"native":  "runc",
		"sandbox": "gvisor",
		"vm":      "kata-containers",
		"foo":     "bar",
	}
	for name, handler := range rcs {
		log.Printf("Creating RuntimeClass %s", name)
		rc := NewRuntimeClass(name, handler)
		_, err := res.Create(rc, metav1.CreateOptions{})
		errExit(fmt.Sprintf("Failed to create RuntimeClass %#v", rc), err)
	}
}

func NewRuntimeClass(name, handler string) *unstructured.Unstructured {
	return &unstructured.Unstructured{
		Object: map[string]interface{}{
			"kind":       "RuntimeClass",
			"apiVersion": runtimeClassGVR.Group + "/v1alpha1",
			"metadata": map[string]interface{}{
				"name": name,
			},
			"spec": map[string]interface{}{
				"runtimeHandler": handler,
			},
		},
	}
}

func PrintRuntimeHandlers(client dynamic.Interface) {
	PrintResourceField(client, runtimeClassGVR, "spec", "runtimeHandler")
}

func PrintResourceField(client dynamic.Interface, gvr schema.GroupVersionResource, fldPath ...string) {
	rs := fmt.Sprintf("%s/%s", gvr.Group, gvr.Resource)
	log.Printf("Listing %s objects", rs)
	res := client.Resource(gvr)
	list, err := res.List(metav1.ListOptions{})
	errExit("Failed to list "+rs+" objects", err)

	log.Printf("Printing %s.%s", rs, strings.Join(fldPath, "."))
	output := make(map[string]string)
	for _, item := range list.Items {
		name := item.GetName()
		fld, exists, err := unstructured.NestedString(item.Object, fldPath...)
		if err != nil {
			log.Printf("Error reading %s for %s: %v", strings.Join(fldPath, "."), name, err)
			continue
		}
		if !exists {
			fld = "[NOT FOUND]"
		}
		output[name] = fld
	}

	for name, fld := range output {
		fmt.Printf("  %-10s  -->  %-10s\n", name, fld)
	}
}

func errExit(msg string, err error) {
	if err != nil {
		log.Fatalf("%s: %#v", msg, err)
	}
}

func userConfig() string {
	usr, err := user.Current()
	errExit("Failed to get current user", err)

	return filepath.Join(usr.HomeDir, ".kube", "config")
}

golang golang各种操作数据库#mongo #file

golang各种操作数据库#mongo #file

file.go
package main;
 
import (
    "os"
    "fmt"
    "strconv"
)
 
func main() {
 
    //打开文件,返回文件指针
    file, error := os.Open("./1.txt");
    if error != nil {
        fmt.Println(error);
    }
    fmt.Println(file);
    file.Close();
 
    //以读写方式打开文件,如果不存在,则创建
    file2, error := os.OpenFile("./2.txt", os.O_RDWR|os.O_CREATE, 0766);
    if error != nil {
        fmt.Println(error);
    }
    fmt.Println(file2);
    file2.Close();
 
    //创建文件
    //Create函数也是调用的OpenFile
    file3, error := os.Create("./3.txt");
    if error != nil {
        fmt.Println(error);
    }
    fmt.Println(file3);
    file3.Close();
 
    //读取文件内容
    file4, error := os.Open("./1.txt");
    if error != nil {
        fmt.Println(error);
    }
    //创建byte的slice用于接收文件读取数据
    buf := make([]byte, 1024);
    //循环读取
    for {
        //Read函数会改变文件当前偏移量
        len, _ := file4.Read(buf);
 
        //读取字节数为0时跳出循环
        if len == 0 {
            break;
        }
 
        fmt.Println(string(buf));
    }
    file4.Close();
 
    //读取文件内容
    file5, error := os.Open("./1.txt");
    if error != nil {
        fmt.Println(error);
    }
    buf2 := make([]byte, 1024);
    ix := 0;
    for {
        //ReadAt从指定的偏移量开始读取,不会改变文件偏移量
        len, _ := file5.ReadAt(buf2, int64(ix));
        ix = ix + len;
        if len == 0 {
            break;
        }
 
        fmt.Println(string(buf2));
    }
    file5.Close();
 
    //写入文件
    file6, error := os.Create("./4.txt");
    if error != nil {
        fmt.Println(error);
    }
    data := "我是数据\r\n";
    for i := 0; i < 10; i++ {
        //写入byte的slice数据
        file6.Write([]byte(data));
        //写入字符串
        file6.WriteString(data);
    }
    file6.Close();
 
    //写入文件
    file7, error := os.Create("./5.txt");
    if error != nil {
        fmt.Println(error);
    }
    for i := 0; i < 10; i++ {
        //按指定偏移量写入数据
        ix := i * 64;
        file7.WriteAt([]byte("我是数据"+strconv.Itoa(i)+"\r\n"), int64(ix));
    }
    file7.Close();
 
    //删除文件
    del := os.Remove("./1.txt");
    if del != nil {
        fmt.Println(del);
    }
 
    //删除指定path下的所有文件
    delDir := os.RemoveAll("./dir");
    if delDir != nil {
        fmt.Println(delDir);
    }
}
gorm.go
// grom 简单的用法

package main

import (
  "github.com/jinzhu/gorm"
  _ "github.com/jinzhu/gorm/dialects/sqlite"
)

type Product struct {
  gorm.Model
  Code string
  Price uint
}

func main() {
  db, err := gorm.Open("sqlite3", "test.db")
  if err != nil {
    panic("failed to connect database")
  }
  defer db.Close()

  // Migrate the schema
  db.AutoMigrate(&Product{})

  // Create
  db.Create(&Product{Code: "L1212", Price: 1000})

  // Read
  var product Product
  db.First(&product, 1) // find product with id 1
  db.First(&product, "code = ?", "L1212") // find product with code l1212

  // Update - update product's price to 2000
  db.Model(&product).Update("Price", 2000)

  // Delete - delete product
  db.Delete(&product)
}
mongo.go
package main

import (
	"fmt"
	"gopkg.in/mgo.v2"
	"gopkg.in/mgo.v2/bson"
	"time"
)

type Content struct {
	Name     string
	Download int
	Date     time.Time
}

var (
	Session, _ = mgo.Dial("localhost")
	Database   = "mgo"
	Collection = "content"
	Coll       = Session.DB(Database).C(Collection)

	content = &Content{
		Name:     "this-is-good-content",
		Download: 1,
		Date:     time.Date(2016, 4, 7, 0, 0, 0, 0, time.UTC),
		//Date: time.Now(),
	}
)

//Drop Database
func dropDatabase() {
	fmt.Println("Drop Database")

	//db.dropDatabase()
	err := Session.DB(Database).DropDatabase()
	if err != nil {
		panic(err)
	}
}

//Insert
func testInsert() {
	fmt.Println("Test Insert into MongoDB")
	c := bson.M{
		"name": "this-is-good-content",
		"download":    1,
		"date":        time.Date(2016, 4, 7, 0, 0, 0, 0, time.UTC),
	}

	/*
		db.content.insert({
			Name: "this-is-good-content",
			Download:    1,
			Date:        new Date("2016-04-07"),
			}
		)
	*/
	Coll.Insert(c)

}

//Multiple Insert
func testMultipleInsert() {
	fmt.Println("Test Multiple Insert into MongoDB")
	var contentArray []interface{}

	/*
		db.content.insert([
			{
				Name: "this-is-good-content",
				Download:    1,
				Date:        new Date("2016-04-07"),
			},
			{
				Name: "this-is-good-content",
				Download:    2,
				Date:        new Date("2016-04-07"),
			},
			{
				Name: "this-is-good-content",
				Download:    3,
				Date:        new Date("2016-04-07"),
			},
			{
				Name: "this-is-good-content",
				Download:    4,
				Date:        new Date(),
			},
			]
		)
	*/
	//contentArray = append(contentArray, &Content{
	//	Name:     "this-is-good-content",
	//	Download: 1,
	//	Date:     time.Date(2016, 4, 7, 0, 0, 0, 0, time.UTC),
	//})
	contentArray = append(contentArray, bson.M{
		"name":     "this-is-good-content",
		"download": 1,
		"date":     time.Date(2016, 4, 7, 0, 0, 0, 0, time.UTC),
	})

	contentArray = append(contentArray, &Content{
		Name:     "this-is-good-content",
		Download: 2,
		Date:     time.Date(2016, 4, 8, 0, 0, 0, 0, time.UTC),
	})

	//same date
	contentArray = append(contentArray, &Content{
		Name:     "this-is-good-content",
		Download: 3,
		Date:     time.Date(2016, 4, 8, 0, 0, 0, 0, time.UTC),
	})

	contentArray = append(contentArray, &Content{
		Name:     "this-is-good-content",
		Download: 3,
		Date:     time.Date(2016, 4, 9, 0, 0, 0, 0, time.UTC),
	})

	contentArray = append(contentArray, &Content{
		Name:     "this-is-good-content2",
		Download: 4,
		Date:     time.Now(),
	})

	Coll.Insert(contentArray...)
}

//Bulk Insert
func testBulkInsert() {
	fmt.Println("Test Bulk Insert into MongoDB")
	bulk := Coll.Bulk()

	var contentArray []interface{}
	contentArray = append(contentArray, &Content{
		Name:     "this-is-good-content",
		Download: 1,
		Date:     time.Date(2016, 4, 7, 0, 0, 0, 0, time.UTC),
	})

	contentArray = append(contentArray, &Content{
		Name:     "this-is-good-content",
		Download: 2,
		Date:     time.Now(),
	})

	bulk.Insert(contentArray...)
	_, err := bulk.Run()
	if err != nil {
		panic(err)
	}
}

//Update
//db.collection.update(
//   <query>,
//   <update>,
//   {
//     upsert: <boolean>,
//     multi: <boolean>,
//     writeConcern: <document>
//   }
//)
func testUpdate() {
	fmt.Println("Test Update in MongoDB")

	//db.content.update({name: "this-is-good-content"})
	selector := bson.M{"name": "this-is-good-content"}

	//Update One and Replace Doc
	//update := bson.M{"download": 3}
	//err := Coll.Update(selector, update)

	//Update One
	//update := bson.M{"$set": bson.M{"download": 3}}
	//err := Coll.Update(selector, update)

	//Update All
	update := bson.M{"$set": bson.M{"download": 3}}
	_, err := Coll.UpdateAll(selector, update)
	if err != nil {
		panic(err)
	}
}

//Upsert
//db.collection.update(
//   <query>,
//   <update>,
//   {
//     upsert: <boolean>,
//     multi: <boolean>,
//     writeConcern: <document>
//   }
//)
func testUpsert() {
	fmt.Println("Test Upsert in MongoDB")

	//Upsert
	update := bson.M{"$inc": bson.M{"download": 3}}
	selector := bson.M{"name": "this-is-good-content3"}

	_, err := Coll.Upsert(selector, update)
	if err != nil {
		panic(err)
	}
}

//Bulk Upsert
func testBulkUpsert() {
	fmt.Println("Test Bulk Upsert in MongoDB")
	bulk := Coll.Bulk()

	//Upsert
	update := bson.M{"$inc": bson.M{"download": 3}}
	selector := bson.M{"name": "this-is-good-content3"}

	bulk.Upsert(selector, update)
	bulk.Upsert(selector, update)
	bulk.Upsert(selector, update)
	_, err := bulk.Run()
	if err != nil {
		panic(err)
	}
}

//Select
func testSelect() {
	fmt.Println("Test Select in MongoDB")
	var result Content
	var results []Content
	var query bson.M
	var err error

	//query := bson.M{"download": 1}
	//Select One
	err = Coll.Find(nil).One(&result)
	if err != nil {
		panic(err)
	}
	fmt.Printf("Select One: %+v\n", result)

	//Select Limit
	iter := Coll.Find(nil).Limit(2).Iter()
	err = iter.All(&results)
	if err != nil {
		panic(err)
	}
	fmt.Printf("Select Limit: %+v\n", results)

	//Select All
	err = Coll.Find(nil).All(&results)
	if err != nil {
		panic(err)
	}
	fmt.Printf("Select All: %+v\n", results)

	//Select with query
	query = bson.M{"name": "this-is-good-content"}
	err = Coll.Find(query).All(&results)
	if err != nil {
		panic(err)
	}
	fmt.Printf("Select contentname: %+v\n", results)

	//Sort (ascending order)
	query = bson.M{"name": "this-is-good-content"}
	err = Coll.Find(query).Sort("download").All(&results)
	if err != nil {
		panic(err)
	}
	fmt.Printf("Ascending sorted Result: %+v\n", results)

	//Sort (descending order)
	query = bson.M{"name": "this-is-good-content"}
	err = Coll.Find(query).Sort("-download").All(&results) //add - left side
	if err != nil {
		panic(err)
	}
	fmt.Printf("Descending sorted Result: %+v\n", results)
}

//Aggregate
func testAggregate() {
	pipeline := []bson.M{
		{"$match": bson.M{"name": "this-is-good-content" }},
		{"$group":
			bson.M{"_id": "$date",
			//bson.M{"_id": "$name",
				"download": bson.M{ "$sum": "$download" },
			},
		},
		{"$sort":
			bson.M{"download": 1},  //1: Ascending, -1: Descending
		},
	}
	pipe := Coll.Pipe(pipeline)

	result := []bson.M{}
	//err := pipe.AllowDiskUse().All(&result) //allow disk use
	err := pipe.All(&result)
	if err != nil {
		panic(err)
	}
	fmt.Println("result:", result)
}

func main() {
	dropDatabase()
	//testInsert()
	testMultipleInsert()
	//testBulkInsert()
	//testUpdate()
	testUpsert()
	//testBulkUpsert()
	testSelect()
	testAggregate()

}
mongo.js
db.col1.ensureIndex({'colors':1})   # 添加index
todo-gin-mgo.go
package main

import (
	"fmt"
	"log"
	"net/http"
	"strconv"

	"github.com/gin-gonic/gin"
	"gopkg.in/mgo.v2"
	"gopkg.in/mgo.v2/bson"
)

type Todo struct {
	ID        bson.ObjectId `bson:"_id,omitempty"`
	Title     string
	Completed bool
}

var todosCollection *mgo.Collection
var session *mgo.Session

func init() {
	session, err := mgo.Dial("127.0.0.1")
	if err != nil {
		panic(err)
	}
	session.SetMode(mgo.Monotonic, true)

	// get a Collection of todo
	todosCollection = session.DB("test-todo").C("todo")
}

func main() {
	defer session.Close()
	router := gin.Default()

	v1 := router.Group("/api/v1/todos")
	{
		v1.POST("/", createTodo)
		v1.GET("/", fetchAllTodo)
		v1.GET("/:id", fetchSingleTodo)
		v1.PUT("/:id", updateTodo)
		v1.DELETE("/:id", deleteTodo)
	}

	router.Run()
}

func createTodo(context *gin.Context) {
	title := context.PostForm("Title")
	completed, _ := strconv.ParseBool(context.PostForm("Completed"))
	var todo = Todo{bson.NewObjectId(), title, completed}
	fmt.Println("" + todo.Title + " completed: " + strconv.FormatBool(todo.Completed))
	err := todosCollection.Insert(&todo)
	if err != nil {
		log.Fatal(err)
	}

	context.JSON(http.StatusCreated, gin.H{
		"status":  http.StatusCreated,
		"message": "todo item created successfully",
	})
}

func fetchAllTodo(context *gin.Context) {
	var todos []Todo
	err := todosCollection.Find(nil).All(&todos)
	if err != nil {
		log.Fatal(err)
	}

	if len(todos) <= 0 {
		context.JSON(http.StatusNotFound, gin.H{
			"status":  http.StatusNotFound,
			"message": "no todo found",
		})
		return
	}

	context.JSON(http.StatusOK, gin.H{
		"status": http.StatusOK,
		"data":   todos,
	})
}

func fetchSingleTodo(context *gin.Context) {
	todo := Todo{}
	id := bson.ObjectIdHex(context.Param("id"))
	err := todosCollection.FindId(id).One(&todo)

	if err != nil || todo == (Todo{}) {
		fmt.Println("Error: " + err.Error())
		context.JSON(http.StatusNotFound, gin.H{
			"status":  http.StatusNotFound,
			"message": "todo not found",
		})
		return
	}

	context.JSON(http.StatusOK, gin.H{
		"status": http.StatusOK,
		"data":   todo,
	})
}

func updateTodo(context *gin.Context) {
	id := bson.ObjectIdHex(context.Param("id"))
	title := context.PostForm("title")
	completed, _ := strconv.ParseBool(context.PostForm("completed"))

	err := todosCollection.UpdateId(id, bson.M{"title": title, "completed": completed})

	fmt.Printf("completed: %t\n\n", completed)

	if err != nil {
		fmt.Println("Error: " + err.Error())
		context.JSON(http.StatusNotFound, gin.H{
			"status":  http.StatusNotFound,
			"message": "todo not found",
		})
		return
	}

	context.JSON(http.StatusOK, gin.H{
		"status":  http.StatusOK,
		"message": "Todo updated successfully!",
	})
}

func deleteTodo(context *gin.Context) {
	id := bson.ObjectIdHex(context.Param("id"))

	fmt.Printf("id: %v", id)

	err := todosCollection.RemoveId(id)

	if err != nil {
		fmt.Println("Error: " + err.Error())
		context.JSON(http.StatusNotFound, gin.H{
			"status":  http.StatusNotFound,
			"message": "todo not found",
		})
		return
	}

	context.JSON(http.StatusOK, gin.H{
		"status":  http.StatusOK,
		"message": "Todo deleted successfully!",
	})
}

golang 水平和垂直计算相同值的块数

水平和垂直计算相同值的块数

Count connected blocks.go
func runTest() {
	arr := [][]string{
		{"a","b", "a", "c", "d", "a"},
		{"a","c", "a", "b", "d", "a"},
		{"a","a", "c", "c", "a", "c"},
	}
 
	var 	v  = make([][]string, len(arr))
	for i, e := range arr {
		v[i] = make([]string, len(e))
	}
	fmt.Println(fill (arr, "", v, 0))
}
 
 
func fill(a [][]string, compareChar string, visited [][]string, count int) (int) {
	var j int
	var i = 0
	var startChar string
	for {
 
		if i >= len(a) {
			return count
		}
		if j >= len(a[i]) {
			i++
			j = 0
			continue
		}
		if visited[i][j] != "" {
			j++
			if j > len(a[i]) {
				i++
				j=0
				continue
			}
			continue
		}
		startChar = a[i][j]
		if startChar == compareChar {
			j++
			continue
		}
		break
	}
 
	if startChar != compareChar {
		visited = find(a, i, j, startChar, visited)
		count++
		count = fill(a, startChar, visited, count)
	}
	return count
}
 
func find(a [][]string, x,y int, startChar string, visited [][]string) [][]string {
	// Base cases
	if x < 0 || x >= len(a) || y < 0 || y >= len(a[x]) {
		return visited
	}
	if a[x][y] != startChar {
		return visited
	}
	if visited[x][y] != "" {
		return visited
	}
	visited[x][y] = a[x][y]
	visited = find(a, x, y + 1, startChar, visited)
 
	visited = find(a, x, y - 1, startChar, visited)
 
	visited = find(a, x + 1, y, startChar, visited)
	return visited
}