Built-in Functions

  • 1
    
    append(s S, x ...E) S  // core type of S is []E
    
    1
    2
    3
    
    s0 := []int{0, 0}
    s1 := append(s0, 3, 5, 7)          // append multiple elements    s2 is []int{0, 0, 3, 5, 7}
    s2 := append(s1, s0...)            // append a slice              s3 is []int{0, 0, 3, 5, 7, 0, 0}
    
  • 1
    2
    
    copy(dst, src []T) int
    copy(dst []byte, src string) int
    
    1
    2
    3
    4
    5
    6
    
    var a = [...]int{0, 1, 2, 3, 4, 5, 6, 7}
    var s = make([]int, 6)
    var b = make([]byte, 5)
    n1 := copy(s, a[0:])            // n1 == 6, s is []int{0, 1, 2, 3, 4, 5}
    n2 := copy(s, s[2:])            // n2 == 4, s is []int{2, 3, 4, 5, 4, 5}
    n3 := copy(b, "Hello, World!")  // n3 == 5, b is []byte("Hello")
    

fmt

1
2
3
4
%v	the value in a default format, when printing structs, the plus flag (%+v) adds field names
%#v	a Go-syntax representation of the value
%T	a Go-syntax representation of the type of the value
%%	a literal percent sign; consumes no value
1
%t	the word true or false
1
2
%c	the character represented by the corresponding Unicode code point
%d	Integer base 10 
1
2
3
4
5
%f	decimal point with default width, default precision
%9f    width 9, default precision
%.2f   default width, precision 2
%9.2f  width 9, precision 2
%9.f   width 9, precision 0
1
%s	the uninterpreted bytes of the string or slice
  • Println(x) is the same as Printf("%v\n", x)
arguments to string writes to io.Writer writes to standard output returns the resulting string
Inserts spaces only between non-string arguments Fprint Print Sprint
according to a format specifier Fprintf Printf Sprintf
Inserts spaces between its arguments and end newline Fprintln Println Sprintln
scans formatted text to yield values read from os.Stidin read from io.Reader read from argument string
treat newlines as spaces Scan Fscan Sscan
according to a format string Scanf Fscanf Sscanf
newline is newline Scanln Fscanln Sscanln

log/slog

1
logger := slog.New()
1
2
3
logger.Info("initiating launch")
logger.Warn("falling back to default value")
logger.Debug("starting background job")
1
2
logger.Error("failed to start engines", "err", "missing fuel")
// sev=ERROR msg="failed to start engines" err="missing fuel"
1
2
3
4
5
6
7
ctx := context.Background()

const LevelEmergency = slog.Level(12)
const LevelTrace     = slog.Level(-8)

logger.Log(ctx, LevelEmergency, "missing pilots")
logger.Log(ctx, LevelTrace, "button clicked")
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
type LevelHandler struct {
	level   slog.Leveler
	handler slog.Handler
}
func NewLevelHandler(level slog.Leveler, h slog.Handler) *LevelHandler {
	// Optimization: avoid chains of LevelHandlers.
	if lh, ok := h.(*LevelHandler); ok {
		h = lh.Handler()
	}
	return &LevelHandler{level, h}
}
th := slog.NewTextHandler(os.Stdout, &slog.HandlerOptions{ReplaceAttr: slogtest.RemoveTime})
logger := slog.New(NewLevelHandler(slog.LevelWarn, th))

Debugging

Debugging Go Code with GDB

Finding Concurrency Problems with the Race Checker

In Go, there are several standard libraries that are essential to master for effective development. Some of the key standard libraries include:

  1. fmt: This library provides functions for formatted I/O, which is crucial for printing and formatting text.
  2. io: The io package contains interfaces and functions for input and output operations, making it fundamental for file handling and data streams.
  3. net: This package is essential for network programming and includes features for creating network clients and servers, working with URLs, and more.
  4. http: If you’re building web applications, the net/http package is indispensable for creating HTTP servers and clients.
  5. json: For working with JSON data, the encoding/json package allows you to marshal and unmarshal data to and from JSON format.
  6. time: This package is used for dealing with time and dates. It’s vital for scheduling tasks, measuring durations, and working with time zones.
  7. sync: When dealing with concurrency and parallelism, the sync package offers synchronization primitives like mutexes and WaitGroups.
  8. os: For interacting with the operating system, including file operations and environment variables, the os package is a must-know.
  9. flag: The flag package enables you to parse command-line arguments easily, which is important for building command-line tools.
  10. log: If you need to log messages and errors in your applications, the log package provides a basic logging framework.
  11. errors: This package offers functions for creating and handling errors in a more structured manner.
  12. context: The context package is used for managing cancellation and deadlines in Go programs, especially in the context of concurrency.

These libraries cover a wide range of functionality and are foundational to most Go projects. Depending on your specific use case, you may also want to explore additional standard libraries and third-party packages to extend Go’s capabilities.

io

io.Writer
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
import	stdlog "log"

var loggers []*Logger
var logLevel = Debug

type Logger struct {
	level  int
	logger *stdlog.Logger
}

func NewLogger(out io.Writer) *Logger {
	ret := &Logger{level: logLevel, logger: stdlog.New(out, "", stdlog.Ldate|stdlog.Ltime|stdlog.Lshortfile)}

	loggers = append(loggers, ret)

	return ret
}
io.MultiWriter
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
func init() {
	rand.Seed(time.Now().UTC().UnixNano())

	log.SetLevel("warn")
	logger = log.NewLogger(os.Stdout)

	model.LoadConf()
	util.LoadMarkdown()
	i18n.Load()
	theme.Load()
	replaceServerConf()

	if "dev" == model.Conf.RuntimeMode {
		gin.SetMode(gin.DebugMode)
	} else {
		gin.SetMode(gin.ReleaseMode)
	}
	gin.DefaultWriter = io.MultiWriter(os.Stdout)
}
io.Copy
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
// CopyFile copies the source file to the dest file.
func (*myfile) CopyFile(source string, dest string) (err error) {
	sourcefile, err := os.Open(source)
	if nil != err {
		return err
	}

	defer sourcefile.Close()

	destfile, err := os.Create(dest)
	if nil != err {
		return err
	}

	defer destfile.Close()

	_, err = io.Copy(destfile, sourcefile)
	if err == nil {
		if sourceinfo, e := os.Stat(source); nil != e {
			err = os.Chmod(dest, sourceinfo.Mode())

			return
		}
	}

	return nil
}

io/ioutil

ioutil.ReadFile
1
data, err := ioutil.ReadFile(path)
ioutil.WriteFile
1
err = ioutil.WriteFile(path, []byte(content), 0644)
ioutil.ReadAll
1
data, err := ioutil.ReadAll(response.Body)
ioutil.ReadDir
1
files, err := ioutil.ReadDir(dirName)

fmt

fmt.Sprint
1
fmt.Sprint(v...)
fmt.Sprintf
1
v := fmt.Sprintf("%d", time.Now().Unix())
fmt.Fprintf
1
fmt.Fprintf(buf, "%s:%d (0x%x)\n", file, line, pc)
fmt.Println
1
fmt.Println(Version)
fmt.Errorf
1
fmt.Errorf("not found category [id=%d] to update", category.ID)

strings

strings.HasSuffix
1
if strings.HasSuffix(path, ".min.js") {}
strings.Contains
1
if !strings.Contains(content, "exports={Server:") {}
strings.Split
1
tmp := "{Server:" + strings.Split(content, "{Server:")[1]
strings.Replace
1
content = strings.Replace(content, json, newJSON, -1)
strings.LastIndex
1
part = part[strings.LastIndex(part, "\"")+1:]
strings.ToLower
1
level = strings.ToLower(level)
strings.NewReader
1
doc, _ := goquery.NewDocumentFromReader(strings.NewReader(contentHTML))
strings.TrimSpace
1
abstractText := strings.TrimSpace(runesToString(runes))
strings.Index
1
if emojiASCII == img[:strings.Index(img, ".")] {}
strings.HasPrefix
1
if strings.HasPrefix(path, reservedPath) {}
strings.Index
1
if idx := strings.Index(mdResult.ContentHTML, "</p>"); 0 < idx {}
strings.TrimPrefix
1
articleSignSetting = strings.TrimPrefix(articleSignSetting, "<p>")
strings.TrimSuffix
1
articleSignSetting = strings.TrimSuffix(articleSignSetting, "</p>")
strings.SplitAfter
1
date := strings.SplitAfter(c.Request.URL.Path, util.PathArchives+"/")[1]
strings.Builder
1
c.Writer = &pjaxHTMLWriter{c.Writer, &strings.Builder{}, c}
1
2
3
4
5
type pjaxHTMLWriter struct {
	gin.ResponseWriter
	bodyBuilder *strings.Builder
	c           *gin.Context
}
strings.Join
1
body = strings.Join(containers, "")

bytes

bytes.Buffer
1
2
3
4
buf := &bytes.Buffer{}
fmt.Fprintf(buf, "%s:%d (0x%x)\n", file, line, pc)
fmt.Fprintf(buf, "\t%s: %s\n", function(pc), source(lines, line))
return buf.Bytes()
1
2
3
builder := bytes.Buffer{}
builder.WriteString("<ul id=\"toc\" class=\"toc\">")
return builder.String()
bytes.NewReader
1
data, err := ioutil.ReadAll(transform.NewReader(bytes.NewReader([]byte(fileName)), simplifiedchinese.GB18030.NewDecoder()))
bytes.Split
1
2
data, err := ioutil.ReadFile(file)
lines = bytes.Split(data, []byte{'\n'})
bytes.Trim
1
return bytes.Trim(lines[n], " \t")
bytes.LastIndex
1
if lastslash := bytes.LastIndex(name, slash); lastslash >= 0 {}
bytes.Index
1
if period := bytes.Index(name, dot); period >= 0 {}
bytes.Replace
1
name = bytes.Replace(name, centerDot, dot, -1)

strconv

strconv.Atoi
1
ret, _ := strconv.Atoi(c.Query("p"))
strconv.Itoa(width)
1
return "width: " + strconv.Itoa(width) + ", height: " + strconv.Itoa(height)
strconv.FormatInt
1
t.Log("size of file [.] is [" + strconv.FormatInt(size, 10) + "]")
1
time := strconv.FormatInt(time.Now().UnixNano(), 10)
strconv.ParseUint
1
parentCmtID, _ := strconv.ParseUint(parentCmtIDArg, 10, 64)
strconv.ParseBool
1
v, err := strconv.ParseBool(setting.Value)
strconv.FormatBool
1
value = strconv.FormatBool(v.(bool))
strconv.ParseInt
1
v, err := strconv.ParseInt(setting.Value, 10, 64)
strconv.FormatFloat
1
value = strconv.FormatFloat(v.(float64), 'f', 0, 64)

regexp

regexp.MustCompile
1
contentHTML = bluemonday.UGCPolicy().AllowAttrs("class").Matching(regexp.MustCompile("^language-[a-zA-Z0-9]+$")).OnElements("code").AllowAttrs("data-src").Sanitize(contentHTML)
1
2
reg := regexp.MustCompile(`\s+`)
ret := reg.ReplaceAllString(tagStr, "")
1
2
reg = regexp.MustCompile(`[\\u4e00-\\u9fa5,\\w,&,\\+,-,\\.]+`)
if !reg.MatchString(tag) {}

unicode

unicode.IsSpace
1
if unicode.IsSpace(runeValue) {}

unicode/utf8

utf8.DecodeRuneInString
1
runeValue, width := utf8.DecodeRuneInString(text[i:])
utf8.ValidString
1
if !utf8.ValidString(fileName) {}

sort

sort.Strings
1
2
3
4
5
var ret []string
for name := range locales {
	ret = append(ret, name)
}
sort.Strings(ret)
sort.Sort
1
2

sort.Sort(articles)

time

time.Now
1
2
time.Now().Unix()
time.Now().UTC().UnixNano()
time.Second
time.Tick
1
for range time.Tick(time.Second * 30) {}
time.Date
time.Unix
1
2
3
4
5
6
7
func RandImage() string {
	min := time.Date(2017, 11, 04, 0, 0, 0, 0, time.UTC).Unix()
	max := time.Now().Unix()
	delta := max - min
	sec := rand.Int63n(delta) + min
	return time.Unix(sec, 0).Format("https://img.hacpai.com/bing/20060102.jpg")
}
time.Millisecond
1
return uint64(time.Now().UnixNano() / int64(time.Millisecond))
time.Sleep

time.Nanosecond

1
time.Sleep(time.Nanosecond)
time.Parse
1
var ZeroPushTime, _ = time.Parse("2006-01-02 15:04:05", "2006-01-02 15:04:05")
time.Time
1
func parseDate(m *map[string]interface{}) time.Time {}
time.Now().Year()
1
time.Now().Year()

math

math.Ceil
1
pageCount := int(math.Ceil(float64(recordCount) / float64(pageSize)))
math.MaxInt32
1
const SyncCommentAuthorID = math.MaxInt32
math.MaxInt8
1
categoryModels := service.Category.GetCategories(math.MaxInt8, blogID)
math.MaxInt64
1
tagModels := service.Tag.GetTags(math.MaxInt64, blogID)

math/rand

rand.Seed
1
rand.Seed(time.Now().UTC().UnixNano())
rand.Intn
1
2
modes := []string{"identicon", "monsterid", "wavatar"}
d := modes[rand.Intn(len(modes))]
rand.Int63n
1
2
3
4
min := time.Date(2017, 11, 04, 0, 0, 0, 0, time.UTC).Unix()
max := time.Now().Unix()
delta := max - min
sec := rand.Int63n(delta) + min
rand.Int
1
v := rand.Int()

os

os.Stdout
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
var logger *log.Logger

func init() {
	rand.Seed(time.Now().UTC().UnixNano())

	log.SetLevel("warn")
	logger = log.NewLogger(os.Stdout)
    //...
	gin.DefaultWriter = io.MultiWriter(os.Stdout)
}
os.Signal
1
c := make(chan os.Signal)
os.Exit
1
2
os.Exit(0)
os.Exit(1)
os.FileInfo
1
func test(path string, f os.FileInfo, err error) error {}
os.Open
1
2
3
f, _ := os.Open(filepath.ToSlash(filepath.Join(model.Conf.StaticRoot, "i18n")))
names, _ := f.Readdirnames(-1)
f.Close()
os.Stat
1
fi, err := os.Stat(path)
os.IsExist
1
if os.IsExist(err) {}
os.Lstat
1
fio, err := os.Lstat(path)
os.Create
os.Chmod
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
// CopyFile copies the source file to the dest file.
func (*myfile) CopyFile(source string, dest string) (err error) {
	sourcefile, err := os.Open(source)
	if nil != err {
		return err
	}

	defer sourcefile.Close()

	destfile, err := os.Create(dest)
	if nil != err {
		return err
	}

	defer destfile.Close()

	_, err = io.Copy(destfile, sourcefile)
	if err == nil {
		if sourceinfo, e := os.Stat(source); nil != e {
			err = os.Chmod(dest, sourceinfo.Mode())

			return
		}
	}

	return nil
}
os.MkdirAll
1
2
3
4
5
sourceinfo, err := os.Stat(source)
if nil != err {
	return err
}
err = os.MkdirAll(dest, sourceinfo.Mode())
os.Args
1
file, _ := exec.LookPath(os.Args[0])
os.Getenv
1
if home := os.Getenv("HOME"); home != "" {}
os.File
1
2
3
4
5
// ZipFile represents a zip file.
type ZipFile struct {
	zipFile *os.File
	writer  *zip.Writer
}
os.ModeDir|os.ModePerm
1
err := os.MkdirAll(filepath.Dir(path), os.ModeDir|os.ModePerm)

os/exec

exec.LookPath
1
2
3
4
5
6
7
// Pwd gets the path of current working directory.
func Pwd() string {
	file, _ := exec.LookPath(os.Args[0])
	pwd, _ := filepath.Abs(file)

	return filepath.Dir(pwd)
}
exec.Command
1
2
3
4
5
6
7
var stdout bytes.Buffer
cmd := exec.Command("sh", "-c", "eval echo ~$USER")
cmd.Stdout = &stdout
if err := cmd.Run(); err != nil {
	return "", err
}
result := strings.TrimSpace(stdout.String())

os/user

user.Current
1
2
3
4
user, err := user.Current()
if nil == err {
	return user.HomeDir, nil
}

os/signal

signal.Notify
1
signal.Notify(c, syscall.SIGINT, syscall.SIGQUIT, syscall.SIGTERM)

path

path.Clean
1
blogURL += path.Clean(url.Path)

path/filepath

filepath.Walk
1
2
3
4
5
6
err = filepath.Walk(unzipPath, func(path string, f os.FileInfo, err error) error {
    if !f.IsDir() {
    	filePaths = append(filePaths, path)
    }
    return err
})
filepath.ToSlash
1
fh.Name = filepath.ToSlash(filepath.Clean(path))
filepath.Join
1
zipPath := filepath.Join(path, name)
filepath.Glob
1
paths, err := filepath.Glob(filepath.ToSlash(filepath.Join(model.Conf.StaticRoot, "console/dist/*.js")))
filepath.Abs
filepath.Dir
1
2
3
4
5
6
func Pwd() string {
	file, _ := exec.LookPath(os.Args[0])
	pwd, _ := filepath.Abs(file)

	return filepath.Dir(pwd)
}
filepath.Base
1
name := filepath.Base(filePath)
filepath.Ext
1
ext := filepath.Ext(mdFile.Name)

testing

testing.T
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
func TestRemoveArticle(t *testing.T) {
	// ...
	if conditions {
		t.FailNow()
		return
	}

	if conditions {
		t.Errorf("exptected is [%d], actual is [%d]", expected, val)

	}
	// ...
	if conditions {
		t.Error("remove article failed")
	}
}

syscall

syscall.SIGINT
syscall.SIGQUIT
syscall.SIGTERM
1
signal.Notify(c, syscall.SIGINT, syscall.SIGQUIT, syscall.SIGTERM)

log

1
import	stdlog "log"
1
2
3
4
type Logger struct {
	level  int
	logger *stdlog.Logger
}
stdlog.New
stdlog.Ldate
stdlog.Ltime
stdlog.Lshortfile
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
const Debug
var loggers []*Logger
var logLevel = Debug

func NewLogger(out io.Writer) *Logger {
	ret := &Logger{level: logLevel, logger: stdlog.New(out, "", stdlog.Ldate|stdlog.Ltime|stdlog.Lshortfile)}

	loggers = append(loggers, ret)

	return ret
}

encoding/json

json.Unmarshal
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
type Configuration struct {
	// ...
}
bytes, err := ioutil.ReadFile(*confPath)
if nil != err {
	logger.Fatal("loads configuration file [" + *confPath + "] failed: " + err.Error())
}
Conf = &Configuration{}
if err = json.Unmarshal(bytes, Conf); nil != err {
	logger.Fatal("parses failed: ", err)
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
type SessionData struct {
	UID     uint64 // user ID
	UName   string // username
	UB3Key  string // user B3 key
	URole   int    // user role
	UAvatar string // user avatar URL
	BID     uint64 // blog ID
	BURL    string // blog url
}
ret := &SessionData{}
err := json.Unmarshal([]byte(sessionDataStr.(string)), ret)
json.Marshal
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
func (sd *SessionData) Save(c *gin.Context) error {
	session := sessions.Default(c)
	sessionDataBytes, err := json.Marshal(sd)
	if nil != err {
		return err
	}
	session.Set("data", string(sessionDataBytes))

	return session.Save()
}

crypto/md5

md5.New
1
2
3
4
mdText = strings.Replace(mdText, "\r\n", "\n", -1)
digest := md5.New()
digest.Write([]byte(mdText))
key := string(digest.Sum(nil))

crypto/tls

tls.Config
tls.Client
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
func dialTLS(network, addr string) (net.Conn, error) {
	conn, err := net.Dial(network, addr)
	if err != nil {
		return nil, err
	}

	host, _, err := net.SplitHostPort(addr)
	if err != nil {
		return nil, err
	}
	cfg := &tls.Config{ServerName: host}

	tlsConn := tls.Client(conn, cfg)
	if err := tlsConn.Handshake(); err != nil {
		conn.Close()
		return nil, err
	}

	cs := tlsConn.ConnectionState()
	cert := cs.PeerCertificates[0]

	cert.VerifyHostname(host)

	return tlsConn, nil
}

net

net.Conn
1
func dialTLS(network, addr string) (net.Conn, error) {}
net.Dial
1
conn, err := net.Dial(network, addr)
net.SplitHostPort
1
host, _, err := net.SplitHostPort(addr)
net.ParseIP
1
2
3
func IsIP(s string) bool {
	return nil != net.ParseIP(s)
}

net/http

http.Server
1
2
3
4
5
6
server := &http.Server{
    Addr:    "0.0.0.0:" + model.Conf.Port,
    Handler: router,
}
handleSignal(server)  // func handleSignal(server *http.Server) {}
server.ListenAndServe()
http.NewRequest
http.DefaultClient
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
request, err := http.NewRequest("POST", "http://localhost:8250", strings.NewReader(""))
if nil != err { 
	return 
}
http.DefaultClient.Timeout = 2 * time.Second
response, err := http.DefaultClient.Do(request)
if nil != err { 
	return 
}
defer response.Body.Close()
data, err := ioutil.ReadAll(response.Body)
if nil != err { 
	return 
}
content := string(data)
http.Transport
http.Request
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
// ExampleAPI is a reverse proxy for https://example.com.
func ExampleAPI() gin.HandlerFunc {
	return func(c *gin.Context) {
		proxy := httputil.NewSingleHostReverseProxy(&url.URL{
			Scheme: "https",
			Host:   "example.com",
		})

		proxy.Transport = &http.Transport{DialTLS: dialTLS}
		director := proxy.Director
		proxy.Director = func(req *http.Request) {
			director(req)
			req.Host = req.URL.Host
			req.URL.Path = req.URL.Path[len("api/hp/"):]
		}

		proxy.ServeHTTP(c.Writer, c.Request)
	}
}
http.Get
1
response, err := http.Get("http://www.example.com/api/v1/res")
http.StatusOK
http.StatusNotFound
http.StatusBadRequest
http.StatusUnauthorized
http.StatusInternalServerError
1
2
3
4
func redirectGitHubLoginAction(c *gin.Context) {
	// ...
	c.JSON(http.StatusOK, result)
}
http.StatusSeeOther
1
2
3
4
func redirectGitHubLoginAction(c *gin.Context) {
	// ...
	c.Redirect(http.StatusSeeOther, path)
}
http.StatusTemporaryRedirect
1
2
3
4
func redirectGitHubLoginAction(c *gin.Context) {
	// ...
	c.Redirect(http.StatusTemporaryRedirect, model.Conf.Server)
}

net/http/httputil

httputil.NewSingleHostReverseProxy
1
2
3
4
proxy := httputil.NewSingleHostReverseProxy(&url.URL{
    Scheme: "https",
    Host:   "hacpai.com",
})

net/url

url.URL
1
2
3
4
proxy := httputil.NewSingleHostReverseProxy(&url.URL{
    Scheme: "https",
    Host:   "example.com",
})
url.Parse
1
2
3
4
server, _ := url.Parse(model.Conf.Server)
if !util.IsDomain(server.Hostname()) {
	return
}
url.PathUnescape
1
path, _ = url.PathUnescape(path)
url.Scheme
url.Host
url.Path
1
2
3
4
5
blogURL = url.Scheme + "://" + url.Host
if "" != url.Path {
	blogURL += path.Clean(url.Path)
}
value = blogURL

errors

errors.New
1
return value, errors.New("what happend")

sync

sync.Mutex
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
// Init service.
var Init = &initService{
	mutex: &sync.Mutex{},
}

type initService struct {
	mutex  *sync.Mutex
	inited bool
}

// Setting service.
var Setting = &settingService{
	mutex: &sync.Mutex{},
}

type settingService struct {
	mutex *sync.Mutex
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
func (srv *initService) InitBlog(blogAdmin *model.User) error {
	srv.mutex.Lock()
	defer srv.mutex.Unlock()

	user := User.GetUserByName(blogAdmin.Name)
	if nil != user && nil != User.GetOwnBlog(user.ID) {
		return nil
	}

	blogID := util.CurrentMillisecond()
	tx := db.Begin()
	if err := srv.initBlog(tx, blogAdmin, blogID); nil != err {
		tx.Rollback()

		return err
	}
	tx.Commit()

	return nil
}

runtime

runtime.GOOS
1
2
3
func IsWindows() bool {
	return "windows" == runtime.GOOS
}
runtime.Caller
1
pc, file, line, ok := runtime.Caller(i)
runtime.FuncForPC
1
fn := runtime.FuncForPC(pc)

archive/zip

zip.Writer
1
2
3
4
5
// ZipFile represents a zip file.
type ZipFile struct {
	zipFile *os.File
	writer  *zip.Writer
}
zip.NewWriter
1
2
3
4
5
6
7
8
// Create a zip file with the specified filename.
func (*myzip) Create(filename string) (*ZipFile, error) {
	file, err := os.Create(filename)
	if nil != err {
		return nil, err
	}
	return &ZipFile{zipFile: file, writer: zip.NewWriter(file)}, nil
}
zip.FileInfoHeader
zip.Deflate
1
2
3
4
5
6
fh, err := zip.FileInfoHeader(fi)
if nil != err {
    return err
}
fh.Name = filepath.ToSlash(filepath.Clean(path))
fh.Method = zip.Deflate // data compression algorithm
zip.File
1
2
3
4
5
6
7
8
9
func cloneZipItem(f *zip.File, dest string) error {
    fileName := f.Name
    if f.FileInfo().IsDir() {}
    fd, err := f.Open()
	if nil != err {
		return err
	}
	defer fd.Close()
}
zip.OpenReader
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
// Unzip extracts a zip file specified by the zipFilePath to the destination.
func (*myzip) Unzip(zipFilePath, destination string) error {
	r, err := zip.OpenReader(zipFilePath)
	if nil != err {
		return err
	}
	defer r.Close()
	for _, f := range r.File {
		err = cloneZipItem(f, destination)
		if nil != err {
			return err
		}
	}
	return nil
}

flag

1
2
3
version := flag.Bool("version", false, "prints current pipe version")
confShowSQL := flag.Bool("show_sql", false, "this will override Conf.ShowSQL if specified")
flag.Parse()

html/template

template.HTML
1
2
3
4
5
type ThemeArticle struct {
	// ...
	Abstract       template.HTML `json:"abstract"`
	// ...
}
1
Content :=   template.HTML(mdResult.ContentHTML)
template.Must
template.New
1
t := template.Must(template.New("").ParseFiles(filepath.ToSlash(filepath.Join(model.Conf.StaticRoot, "theme/comment/comment.html"))))

text/template

template.ParseFiles
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
func showIndexAction(c *gin.Context) {
	t, err := template.ParseFiles(filepath.ToSlash(filepath.Join(model.Conf.StaticRoot, "console/dist/index.html")))
	if nil != err {
		logger.Errorf("load index page failed: " + err.Error())
		c.String(http.StatusNotFound, "load index page failed")

		return
	}

	t.Execute(c.Writer, nil)
}