Skip to content

Commit

Permalink
commit
Browse files Browse the repository at this point in the history
  • Loading branch information
xiantang committed Oct 8, 2023
1 parent 05461cf commit 049e9a9
Show file tree
Hide file tree
Showing 14 changed files with 1,515 additions and 0 deletions.
253 changes: 253 additions & 0 deletions content/post/make_zero_value_useful.en.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,253 @@
---
title: "Golang: Making Your Zero Values More Useful"
date: 2022-01-16T15:04:40+08:00
author: "xiantang"
# lastmod:
tags: ["Chinese", "Golang"]
categories: ["Golang"]
images:
- ./post/make_zero_value_useful.png
description: Golang uses zero values to make your code more concise, including Golang json zero value, Golang map zero value, etc.
draft: false
---


<!--
* Always start with a sentence to synchronize the background and context
* Comment-style writing quotes some big cows
* More interesting jump links
* Recommend some interesting links at the end of the article
* Write the outline first, then the content -->

> Make the zero value useful.
--Go Proverbs

Let's start with the Golang blog: [The zero value](https://go.dev/ref/spec#The_zero_value)
> When memory is allocated to store a value, whether by declaration or by calling make or new, and no explicit initialization is provided, the memory is given a default initialization. Each element of this value is set to its type's zero value: false for booleans, 0 for integers, 0.0 for floats, `""` for strings, and nil for pointers, functions, interfaces, slices, channels, and maps. This initialization is done recursively, so, for example, if no value is specified, each element of a structure array will be zeroed.
Setting a value to zero in this way provides a great guarantee for the safety and correctness of the program, and also ensures the readability and simplicity of the program. This is what Golang programmers call "Make the zero value useful".

## Zero value cheat sheet

| Type | Zero Value |
| --- | --- |
| bool | false |
| int | 0 |
| float | 0.0 |
| string | "" |
| pointer | nil |
| function | nil |
| slice | nil |
| map | nil |
| channel | nil |

The initialization of zero values is recursive, so if no value is specified, each element of the structure array will be zeroed.

```golang
➜ gore --autoimport
gore version 0.5.3 :help for help
gore> var a [10]int
gore> a
[10]int{
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
}
```

The same is true for structures. We initialize a B structure that references A, and if no value is specified, each field of B will be zeroed.

```golang
➜ gore --autoimport
gore version 0.5.3 :help for help
gore> type A struct { i int; f float64 }
gore> type B struct { i int; f float64; next A }
gore> new(B)
&main.B{
i: 0,
f: 0.000000,
next: main.A{
i: 0,
f: 0.000000,
},
}
```

note:

* new: new(T) returns a pointer to the `zero value` of the newly allocated T type.
* The tool used is [gore](https://github.com/x-motemen/gore)

## Usage of Zero Values

The previous section has introduced what zero values are, here we will see how to use them.

### sync.Mutex

Here is an example of sync.Mutex, sync.Mutex is designed to be used directly through zero values without explicit initialization.

```golang
package main

import "sync"

type MyInt struct {
mu sync.Mutex
val int
}

func main() {
var i MyInt

// i.mu is usable without explicit initialisation.
i.mu.Lock()
i.val++
i.mu.Unlock()
}
```

Thanks to the characteristics of zero values, the two unexported variables inside Mutex will be initialized to zero values. So the zero value of sync.Mutex is an unlocked Mutex.

```golang
// A Mutex is a mutual exclusion lock.
// The zero value for a Mutex is an unlocked mutex.
//
// A Mutex must not be copied after first use.
type Mutex struct {
state int32
sema uint32
}
```

### bytes.Buffer

Another example is bytes.Buffer, its zero value is an empty Buffer.

```golang
package main

import "bytes"
import "io"
import "os"

func main() {
var b bytes.Buffer
b.Write([]byte("go go go"))
io.Copy(os.Stdout, &b)
}
```

### JSON omitempty

JSON receivers also accept the `omitempty` flag, when the input field is a `zero value`, the receiver will ignore this field.

```golang
➜ gore --autoimport
gore version 0.5.3 :help for help
gore> type Person struct {
..... Name string `json:"name"`
..... Age int `json:"age"`
..... Addr string `json:"addr,omitempty"`
..... }
gore> p1 := Person{
..... Name: "taoge",
..... Age: 30,
..... }
main.Person{
Name: "taoge",
Age: 30,
Addr: "",
}
gore> data, err := json.Marshal(p1)
...
gore> string(data)
"{\"name\":\"taoge\",\"age\":30}"
```

### channel close

In [Channel Axioms](https://dave.cheney.net/2014/03/19/channel-axioms), there is also a rule related to zero values, when the channel is closed, the <- operation on the closed channel always returns `zero value` immediately.

```golang
package main

import "fmt"

func main() {
c := make(chan int, 3)
c <- 1
c <- 2
c <- 3
close(c)
for i := 0; i < 4; i++ {
fmt.Printf("%d ", <-c) // prints 1 2 3 0
}
}
```

The correct way to solve the above problem is to use a for loop:

```golang
for v := range c {
// do something with v
}

```

### Value not found for corresponding key in map

For a map, if the corresponding key is not found, the map will return a zero value of the corresponding type.

```golang
➜ gore --autoimport
gore version 0.5.3 :help for help
gore> a := make(map[string]string)
map[string]string{}
gore> a["123"] = "456"
"456"
gore> a["000"]
""
```

The solution to this problem is to return multiple values:

```golang
gore --autoimport
gore version 0.5.3 :help for help
gore> a := make(map[string]string)
map[string]string{}
gore> c,ok := a["000"]
""
false
```

For non-existent keys, the value of ok will become false.

## Summary

The above is some experience summary about `zero value`. I hope everyone can use the `zero value` better when designing code, and use the features provided by `zero value` to initialize some variables.

## Related Links

* [Golang zero value](https://dave.cheney.net/2013/01/19/what-is-the-zero-value-and-why-is-it-useful)
* [《Channel Axioms》](https://dave.cheney.net/2014/03/19/channel-axioms)
* [Go REPL](https://github.com/x-motemen/gore)

## Article Recommendations

Finally, I would like to share with you some good articles I have been reading recently. I wanted to send them in a weekly format, but because I read them in a scattered way, I put them at the end of each blog post, hoping everyone can gain something.

* [Why we don't have children](https://shuxiao.wang/posts/why-no-new-baby/) Some thoughts about having children
* [Detailed interpretation of the paper "The Tail At Scale"](https://blog.csdn.net/LuciferMS/article/details/122522964)
* [Writing maintainable Go code](https://jogendra.dev/writing-maintainable-go-code) Many points resonate with me after practice. The code is written once, but it will be read hundreds of times, so writing maintainable code is very important.
* [Advanced Golang concurrency programming talk](https://go.dev/blog/io2013-talk-concurrency) The sharer provides actual concurrency problems and then gives some of his own solutions. Very beneficial.
* [pprof graphic explanation](https://github.com/google/pprof/blob/master/doc/README.md#interpreting-the-callgraph) Finally, I can read pprof.

Sure, please provide the Markdown content you want to translate. I'll make sure to follow the rules you've outlined.
129 changes: 129 additions & 0 deletions content/post/neovim.en.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
---
title: "Using neovim as a PDE (Personalized Development Environment)"
date: 2022-10-29T20:45:20+08:00
author: "xiantang"
# lastmod:
tags: ["neovim"]
categories: ["neovim"]
images:
- ./post/neovim.png
description:
draft: false
---


<!-- * Always start with a sentence, synchronizing background and context -->
<!-- * What you can learn from this article -->
<!-- * Comment-style writing quotes some big shots -->
<!-- * More interesting jump links -->
<!-- * Recommend some interesting links at the end of the article -->
<!-- * Write the outline first, then the content -- -->

This article will not tell you how to configure neovim step by step, but will tell you some "Tao" about PDE, not the specific practice of "Art".

## Introduction to neovim and PDE

Seeing TJ's YouTube introduced the use of neovim as a PDE, it was interesting, so I tried it myself, it felt good, so I recorded it.

### What is neovim

Neovim is a branch of vim, vim is a text editor, neovim is a branch of vim, its goal is to provide a better vim, not a substitute for vim.

What's the difference between neovim and vim?
The difference is that neovim has refactored vim's code, supports lua scripts as configuration language on the basis of compatible vimscipt. At the same time, neovim's community on Github is more active than vim's. Neovim has a more useful lsp server, you can understand neovim is a superset of vim.


### What is PDE

PDE is a personalized development environment, which means that on the basis of meeting basic development needs, users can script and customize their development environment, thereby improving user development experience and efficiency.


As you continue to solve the pain points in your development environment, your development efficiency will get higher and higher, and your development experience will get better and better, this is the charm of PDE.

You can also continue to learn new things from it, in this process, you will also get a sense of accomplishment.


## Basic needs to be met


Define the basic needs that your PDE needs to meet, such as:

* Highlighting
* lsp
* Basic refactoring rename
* Quick jump
* lint
* Code suggestion
* Code snippet
* Debugging
* Quickly find recent files

Because only by satisfying these basic needs can you ensure that you will not return to your old editor. Keep finding your own pain points on top of this, and then solve them, you will get faster and faster and master this tool more and more.

## Personalized needs

Sometimes I always have some interesting needs, let me just give an example:

For example, I often modify multiple projects in vim at the same time, but NERDTreeFind in nerdtree will only find from the current tree, and the root directory of the tree is always wrong. My requirement is to find this file in the bookmarks of nerdtree, and the root directory is the first matched bookmark.

![show off](https://user-images.githubusercontent.com/34479567/204140677-0c11c2c8-cca7-44d2-8971-12632e3f0874.gif)

You can refer to my implementation:

https://github.com/xiantang/nvim-conf/blob/dev/lua/nerdtree.lua

Basically all the functions you want can be achieved by modifying lua, or by using nvim series plugins.

1. For example, quickly call up a terminal or a note txt
2. Add some custom snippets
3. And so on...

## Better configuration management

In fact, when everyone uses neovim to make their own PDE, they will find that you can easily mess up your neovim, because there are many plugins in your configuration, and these plugins are often incompatible. So the following two points are crucial:

1. Quickly roll back the configuration to a stable version
2. Quickly find out which version introduced the problem

### Use git as the configuration management of neovim

This is actually very simple, you just need to put your configuration file in a git repository.

You can use your most stable branch as the master, and then you usually modify it on the dev branch. When you want a function, you can modify it on the dev branch, and then use it for a while. When the function is stable, merge it into the master.

If the stable version of the master branch has a problem, I recommend a god command of git, git-bisect. You can set a behavior error version and a historical behavior correct version. This command will use a binary method to help you find out which version introduced this problem.

### Troubleshooting

There are several main commands:

`checkhealth` checks the health of your neovim, such as whether your neovim supports lua, whether it supports python, whether the plugin dependencies are successfully installed, etc.
`nvim --startuptime` records the startup time of your neovim. You can use this to find out which plugin is slowing down your neovim startup. You can also use the Startuptime plugin to view your neovim startup time.
`verbose <map type> <key>` displays detailed information about your key mapping, such as whether your key mapping is successful, whether there are conflicts, etc.
`lua =vim.inspect(var)` prints the information of the variable you need.

## No need to switch suddenly, you can use ideavim and then switch slowly

If you are not very familiar with (neo)vim, I suggest you try running the vimtutor command first to learn the basic operations of vim.
Then you can use vim shortcuts in jetbrains using ideavim, so you can slowly switch to neovim.
Pure vim development is not achieved overnight, it takes some time to adapt, but I believe you will love it.

## Don't blindly use other people's configurations directly

In addition, neovim actually has many derivative distributions. My suggestion is that if you are not very familiar with neovim, do not directly use other people's configurations, because you may encounter many problems, but you may not be able to solve these problems yourself, so if you want to use it, try to build your own configuration from other people's Minimal templates.


## Interesting things
* Use firenvim as a browser editor to brush leetcode [twitter](https://twitter.com/GIA917229015/status/1573365264439480321)
* Use grammarly as an English language server to check your grammar errors

## END

Your PDE is just the most suitable for your environment, this article does not provide the author's configuration, what suits me may not suit you.

## References
* [PDE: A different take on editing code](https://www.youtube.com/watch?v=QMVIJhC9Veg&t=836s&ab_channel=TJDeVries)
* [nvim-lua-guide](https://github.com/nanotee/nvim-lua-guide)
* [jdhao](https://jdhao.github.io/)

Sure, please provide the Markdown content you want to translate.
Loading

0 comments on commit 049e9a9

Please sign in to comment.