围棋规则 斜着连成一条线_进入围棋世界的第一步

围棋规则 斜着连成一条线

由于开发人员每年都要学习一种新的编程语言 ,我觉得现在是时候投入新的东西了,我决定使用Go

好消息是Go拥有很棒的文档来帮助您入门。 更好的消息是Go拥有成熟的工具生态系统 ,包括对获取依赖项,格式化和测试的支持。

还有一个支持Go的Eclipse插件 。 尽管它不像对Java的支持那样完整(例如,很少有快速修复或重构),但是它比我尝试过的其他语言要好得多。

学习任何东西的最好方法是边做边 ,所以我从简单的kata开始:开发集合类型。 Go的标准库不提供set ,但这是重点。 我只想通过学习一些熟悉的东西来学习语言。

因此,让我们开始第一个测试。 Go中的约定是,如果要测试foo.go ,则创建一个名称为foo_test.go的文件。

package set
 
import (
  "testing"
)
 
func TestEmpty(t *testing.T) {
  empty := NewSet()
  if !empty.IsEmpty() {
    t.Errorf("Set without elements should be empty")
  }
}

(WordPress当前不支持Go语法高亮显示,因此func关键字不会这样显示。)

关于这段代码,有几件事要注意:

  • Go使用package语句支持包
  • 语句以分号( ; )终止,但是您可以在行的末尾忽略它们,就像在Groovy中一样
  • 您可以使用import语句导入包。 testing包是标准库的一部分
  • 以小写字母开头的所有内容都是包的私有内容,以大写字母开头的所有内容都是公共的
  • Go中的代码进入函数内部,如func关键字所示
  • 变量名称写在类型之前
  • :=语法是声明和初始化变量的简写; 去会找出正确的类型
  • Go没有构造函数 ,但是使用工厂函数来实现相同的功能
  • if语句不需要在条件周围加上括号,但是需要大括号
  • testing包很小,并且没有断言。 虽然有提供这些功能的软件包,但我决定在此处保持默认值

因此,让我们通过测试:

package set
 
type set struct {
}
 
func NewSet() *set {
  return new(set)
}
 
func (s *set) IsEmpty() bool {
  return true
}

关于Eclipse插件的最酷的事情是,只要保存文件,它就会自动运行测试,就像InfiniTest for Java一样。 当您进行测试驱动开发时,这真的很好。

现在,这当然不是一个测试,因为它仅测试IsEmpty()硬币的一侧。 这就是让我们伪造实现的原因。 因此,让我们修复测试:

func TestEmpty(t *testing.T) {
  empty := NewSet()
  one := NewSet()
  one.Add("A")
  if !empty.IsEmpty() {
    t.Errorf("Set without elements should be empty")
  }
  if one.IsEmpty() {
    t.Errorf("Set with one element should not be empty")
  }
}

我们可以轻松通过:

type set struct {
  empty bool
}
 
func NewSet() *set {
  s := new(set)
  s.empty = true
  return s
}
 
func (s *set) IsEmpty() bool {
  return s.empty
}
 
func (s *set) Add(item string) {
  s.empty = false
}

请注意,我已经使用string类型作为Add()的参数。 我们显然希望有更通用的东西,但是Go中没有Object ,而Java中没有。 稍后我将重新讨论该决定。

下一个测试将验证集合中的项目数:

func TestSize(t *testing.T) {
  empty := NewSet()
  one := NewSet()
  one.Add("A")
  if empty.Size() != 0 {
    t.Errorf("Set without elements should have size 0")
  }
  if one.Size() != 1 {
    t.Errorf("Set with one element should have size 1")
  }
}

我们通过将empty归纳为size来传递:

type set struct {
  size int
}
 
func NewSet() *set {
  s := new(set)
  s.size = 0
  return s
}
 
func (s *set) IsEmpty() bool {
  return s.Size() == 0
}
 
func (s *set) Add(item string) {
  s.size++
}
 
func (s *set) Size() int {
  return s.size
}

现在测试通过了,我们需要对其进行一些清理:

var empty *set
var one *set
 
func setUp() {
  empty = NewSet()
  one = NewSet()
  one.Add("A")
}
 
func TestEmpty(t *testing.T) {
  setUp()
  if !empty.IsEmpty() {
    t.Errorf("Set without elements should be empty")
  }
  if one.IsEmpty() {
    t.Errorf("Set with one element should not be empty")
  }
}
 
func TestSize(t *testing.T) {
  setUp()
  if empty.Size() != 0 {
    t.Errorf("Set without elements should have size 0")
  }
  if one.Size() != 1 {
    t.Errorf("Set with one element should have size 1")
  }
}

再次注意,与例如JUnit相比,缺少测试基础结构支持。 我们必须手动调用setUp()函数。

使代码的形状更好,让我们添加下一个测试:

func TestContains(t *testing.T) {
  setUp()
  if empty.Contains("A") {
    t.Errorf("Empty set should not contain element")
  }
  if !one.Contains("A") {
    t.Errorf("Set should contain added element")
  }
}

要进行此传递,我们必须将项目实际存储在集合中,这需要使用数组切片

type set struct {
  items []string
}
 
func NewSet() *set {
  s := new(set)
  s.items = make([]string, 0, 10)
  return s
}
 
func (s *set) Add(item string) {
  s.items = append(s.items, item)
}
 
func (s *set) Size() int {
  return len(s.items)
}
 
func (s *set) Contains(item string) bool {
  for _, value := range s.items {
    if (value == item) {
      return true
    }
  }
  return false
}

切片是一种方便的类似数组的数据结构,由真实的ray支持。 数组不能改变大小,但是可以大于它们返回的切片。 这样可以保持将项目附加到切片的效率。

for循环是Go中唯一的循环构造,但是它比大多数其他语言的for强大得多。 它同时提供了索引和值,我们首先使用下划线( _ )忽略了索引和值。 它使用range关键字遍历切片中的所有项目。

因此,现在我们有了各种各样的集合,但还没有一套:

func TestIgnoresDuplicates(t *testing.T) {
  setUp()
  one.Add("A")
  if one.Size() != 1 {
    t.Errorf("Set should ignore adding an existing element")
  }
}
func (s *set) Add(item string) {
  if !s.Contains(item) {
    s.items = append(s.items, item)
  }
}

我们要做的只是使所有功能都可以移除:

func TestRemove(t *testing.T) {
  setUp()
  one.Remove("A")
 
  if one.Contains("A") {
    t.Errorf("Set still contains element after removing it")
  }
}
func (s *set) Remove(item string) {
  for index, value := range s.items {
    if value == item {
      s.items[index] = s.items[s.Size() - 1]
      s.items = s.items[0:s.Size() - 1]
    }
  }
}

在这里,我们看到了for循环的完整形式,包括索引和值。 此循环与Contains()循环非常相似,因此我们可以提取一种方法来消除重复:

func (s *set) Contains(item string) bool {
  return s.indexOf(item) >= 0
}
 
func (s *set) indexOf(item string) int {
  for index, value := range s.items {
    if value == item {
      return index
    }
  }
  return -1
}
 
func (s *set) Remove(item string) {
  index := s.indexOf(item)
  if index >= 0 {
    s.items[index] = s.items[s.Size()-1]
    s.items = s.items[0 : s.Size()-1]
  }
}

请注意indexOf()上的小写起始字母,使其成为私有方法。 由于我们的集合是无序的,因此公开此功能没有任何意义。

最后,我们需要对集合进行概括,以便它可以包含任何类型的项目:

func TestNonStrings(t *testing.T) {
  set := NewSet()
 
  set.Add(1)
  if !set.Contains(1) {
    t.Errorf("Set does not contain added integer")
  }
 
  set.Remove(1)
  if set.Contains(1) {
    t.Errorf("Set still contains removed integer")
  }
}

一些挖掘表明,我们可以使用一个空接口在Go中模仿Java的Object

type set struct {
  items []interface{}
}
 
func NewSet() *set {
  s := new(set)
  s.items = make([]interface{}, 0, 10)
  return s
}
 
func (s *set) IsEmpty() bool {
  return s.Size() == 0
}
 
func (s *set) Add(item interface{}) {
  if !s.Contains(item) {
    s.items = append(s.items, item)
  }
}
 
func (s *set) Size() int {
  return len(s.items)
}
 
func (s *set) Contains(item interface{}) bool {
  return s.indexOf(item) >= 0
}
 
func (s *set) indexOf(item interface{}) int {
  for index, value := range s.items {
    if value == item {
      return index
    }
  }
  return -1
}
 
func (s *set) Remove(item interface{}) {
  index := s.indexOf(item)
  if index >= 0 {
    s.items[index] = s.items[s.Size()-1]
    s.items = s.items[0 : s.Size()-1]
  }
}

总而言之,我发现在Go中工作非常愉快。 语言简单但功能强大。 go fmt了有关代码布局的讨论,编译器对if.括号的坚持也是if. Go真正闪耀的地方是并发编程,但这又是另一回事了。

你怎么看? 您喜欢这种经过修饰的小语言吗? 你会用吗? 请在评论中留言。

翻译自: https://www.javacodegeeks.com/2016/02/first-steps-world-go.html

围棋规则 斜着连成一条线

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值