这段代码是否符合 Golang 的惯用写法?持久化树。

huangapple go评论74阅读模式
英文:

Is this code in Golang idiomatic ? Persisten tree

问题

我正在学习Go语言,并尝试实现一个不太简单的持久平衡树,我想知道我写的代码是否符合惯用方式。

以下是不完整的代码:

package main

import (
	"fmt"
	"errors"
)

type Node struct {
	value int
	left  *Node
	right *Node
}

func TraverseTree(root Node) {
	if root.value != 0 {
		TraverseTree(*root.left)
		fmt.Println(root.value)
		TraverseTree(*root.right)
	}
	return
}

func MakeNode(value int) Node {
	node := Node{value: value,
		right: &Node{},
		left:  &Node{}}
	return node
}

func AddNode(root Node, value int) (newNode Node, err error) {
	alreadyPresentError := errors.New("Element already present")
	if root.value == 0 {
		fmt.Println("Creating new Node of value: ", value)
		newNode = MakeNode(value)
		err = nil
	} else if root.value == value {
		newNode = root
		err = alreadyPresentError
	} else if value > root.value { //going right
		fmt.Println("Going Right")
		nodeLeft, err := AddNode(*root.right, value)
		if err != nil {
			newNode = root
			err = alreadyPresentError
		} else {
			newNode = Node{value: root.value,
				left:  root.left,
				right: &nodeLeft}
			err = nil
		}
	} else if value < root.value { //going left
		fmt.Println("Going left")
		nodeRight, err := AddNode(*root.left, value)
		if err != nil {
			newNode = root
			err = alreadyPresentError
		} else {
			newNode = Node{value: root.value,
				left:  &nodeRight,
				right: root.right}
			err = nil
		}
	}
	return
}

我对代码不太满意的地方是如何处理错误,但可能还有其他错误。

英文:

I am learning GO and I am trying to implement something not too trivial, a persistent balanced tree and I am wonder if the code I wrote is idiomatic or not.

Here is the incomplete code:

package main
import (
&quot;fmt&quot;
&quot;errors&quot;
)
type Node struct{
value int
left * Node
right * Node
}
func TraverseTree(root Node) {
if root.value != 0 {
TraverseTree(*root.left)
fmt.Println(root.value)
TraverseTree(*root.right)}
return
}
func MakeNode(value int) (Node) {
node := Node{value: value,
right: &amp;Node{},
left:  &amp;Node{}}
return node
}
func AddNode(root Node, value int) (newNode Node, error error){
alreadyPresentError := errors.New(&quot;Element already present&quot;)
if root.value == 0 {
fmt.Println(&quot;Creating new Node of value: &quot;, value)
newNode = MakeNode(value)
error = nil
} else if root.value == value {
newNode = root
error = alreadyPresentError
}else if value &gt; root.value{ //going right
fmt.Println(&quot;Going Right&quot;)
nodeLeft, err := AddNode(*root.right, value)
if err != nil {
newNode = root
err = alreadyPresentError
}else{
newNode = Node{value: root.value, 
left:  root.left, 
right: &amp;nodeLeft}
error = nil}
}else if value &lt; root.value{ //going left
fmt.Println(&quot;Going left&quot;)
nodeRight, err := AddNode(*root.left, value)
if err != nil {
newNode = root
err = alreadyPresentError
}else{
newNode = Node{value: root.value, 
left:  &amp;nodeRight, 
right: root.right}
error = nil}}
return
}

What doesn't really convince me is how I manage the error, but probably there are some other error.

答案1

得分: 1

有几件事情需要处理:

  • 始终使用 go fmt 格式化你的代码
  • 使用 switch 而不是 if-else 链

其余部分更多是品味问题。你可能可以通过不使用命名返回值来使代码更清晰,但这是我的意见。以下是我的建议:

// 将其移到这里以重用单个错误实例
var alreadyPresentError = errors.New("元素已存在")
func AddNode(root Node, value int) (Node, error) {
switch {
case root.value == 0:
fmt.Println("创建值为:", value, "的新节点")
return MakeNode(value), nil
case root.value == value:
return root, alreadyPresentError
case value > root.value:
// 向右走
fmt.Println("向右走")
nodeLeft, err := AddNode(*root.right, value)
if err != nil {
return root, alreadyPresentError
}
return Node{value: root.value,
left:  root.left,
right: &nodeLeft}, nil
case value < root.value: // 向左走
fmt.Println("向左走")
nodeRight, err := AddNode(*root.left, value)
if err != nil {
return root, alreadyPresentError
}
return Node{value: root.value,
left:  &nodeRight,
right: root.right}, nil
}
// 虚拟返回。如果你不喜欢虚拟返回,可以删除 case root.value == value 的情况
return root, alreadyPresentError
}
英文:

There are a couple of things that should be dealt with:

  • Always format your code with go fmt
  • Use switch instead of if-else chains

The rest is more a matter of taste. You could probably make the code more clear by not using named return values, but that is my oppinion. Below is my suggestion:

// Moved it up here to reuse a single instance of the error
var alreadyPresentError = errors.New(&quot;Element already present&quot;)
func AddNode(root Node, value int) (Node, error) {
switch {
case root.value == 0:
fmt.Println(&quot;Creating new Node of value: &quot;, value)
return MakeNode(value), nil
case root.value == value:
return root, alreadyPresentError
case value &gt; root.value:
//going right
fmt.Println(&quot;Going Right&quot;)
nodeLeft, err := AddNode(*root.right, value)
if err != nil {
return root, alreadyPresentError
}
return Node{value: root.value,
left:  root.left,
right: &amp;nodeLeft}, nil    
case value &lt; root.value: //going left
fmt.Println(&quot;Going left&quot;)
nodeRight, err := AddNode(*root.left, value)
if err != nil {
return root, alreadyPresentError
}
return Node{value: root.value,
left:  &amp;nodeRight,
right: root.right}, nil    
}
// Dummy return. If you don&#39;t like dummies, delete the case root.value == value case
return root, alreadyPresentError
}

huangapple
  • 本文由 发表于 2013年11月16日 08:29:48
  • 转载请务必保留本文链接:https://go.coder-hub.com/20013060.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定