为什么我们需要使用*来修改基本数据类型的值,而不是用户定义的结构的值?

I am new to Go and have some experience in C. Now the thing which confuses me the most is why, in the code below, we need to dereference str to modify value but not chk.j.

What additional thing is happening in here in the case of structs?

type test struct {
    i int
    j string
}

func main() {
    str := new(string)
    *str = "Need Astrik"
    chk := new(test)
    chk.i = 5
    chk.j = "Confused"
    fmt.Println("printing", chk.i, chk.j, *str)
}

See Selectors section in the spec:

Selectors automatically dereference pointers to structs. If x is a pointer to a struct,x.y is shorthand for (*x).y; if the field y is also a pointer to a struct, x.y.z is shorthand for (*(*x).y).z, and so on. If x contains an anonymous field of type *A, where A is also a struct type, x.f is shorthand for (*x.A).f.

In summary: pointer members of structs are dereferenced automatically.

For assignments there's no such shortcut, so assigning pointees is the same as in C:

*p = value

In the case of struct x with a member y that is a pointer you want to assign its target a value to:

*x.y = value

In case the x is a pointer to a struct, the expression above translates to

*((*x).y) = value

new creates a pointer. If you want to assign something to what the pointer is pointing to, you need to dereference it. If you didn't create your values with new, you wouldn't need to dereference any pointers:

//without magic := so you actually see the types of things
  package main
import "fmt"

func main(){
    var s string = "Hello World"
    s = "hello"
    var sp (*string) = &s
    fmt.Println(s) //hello
    fmt.Println(*sp) //hello
    *sp = "world"
    fmt.Println(s) //world
    fmt.Println(*sp) //world
}

You don't need to dereference your test chk because . can behave like both -> and . from C depending on whether you use it on a struct or a pointer to a struct.