# Distributed Services with Go - Method log.Read() fails reading Records

**URL:** <https://forum.devtalk.com/t/distributed-services-with-go-method-log-read-fails-reading-records/733>\
**Category:** PragProg Customers\
**Tags:** book-distributed-services-with-go, errata\
**Created:** [10 June 2020 07:14 UTC](https://forum.devtalk.com/t/distributed-services-with-go-method-log-read-fails-reading-records/733 "2020-06-10T07:14:46Z")\
**Posts on this page:** 2\
**Page:** 1

<div class="post-metadata">

**Author:** ![seblegall](https://forum.devtalk.com/user_avatar/forum.devtalk.com/seblegall/32/1002_2.png) [@seblegall](https://forum.devtalk.com/u/seblegall)\
**Post date:** [10 June 2020 07:14 UTC](https://forum.devtalk.com/t/distributed-services-with-go-method-log-read-fails-reading-records/733/1 "2020-06-10T07:14:46Z")

</div>

Hi,

I’m currently reading your book. By doing so, I like to rewrite the code by myself. It helps me to deeply understand how it works.

However, I found something strange in the log package, concerning the Read() func. Let’s see that with a test example :

In the `log_test.go` file, the original test is :

```auto
func testAppendRead(t *testing.T, log *log.Log) {
	append := &api.Record{
		Value: []byte("hello world"),
	}
	off, err := log.Append(append)
	require.NoError(t, err)
	require.Equal(t, uint64(0), off)

	read, err := log.Read(off)
	require.NoError(t, err)
	require.Equal(t, append, read)

}

```

In this test, we write 1 record and read it.  
Let’s write 4 records and read them:

```auto
func testAppendRead(t *testing.T, log *log.Log) {

	for i := 0; i < 5; i++ {
		append := &api.Record{
			Value: []byte(fmt.Sprintf("Hello World %d !", i)),
		}
		off, err := log.Append(append)
		require.NoError(t, err)
		require.Equal(t, uint64(i), off)

		read, err := log.Read(off)
		require.NoError(t, err)
		require.Equal(t, append, read)
	}

}

```

Here is what I get by running `go test -v log_test.go` :

```auto
=== RUN TestLog
=== RUN TestLog/append_and_read_a_record_succeeds
    TestLog/append_and_read_a_record_succeeds: log_test.go:48: 
                Error Trace: log_test.go:48
                                                        log_test.go:32
                Error: Received unexpected error:
                                offset out of range: 2
                Test: TestLog/append_and_read_a_record_succeeds

```

I’m not sure why it fails, but I have understood that, in a log, segments are ordered from the oldest to the newest. It means the oldest will have a base offset of 0 (for example), the second will have a base offset of 2.

But then, there is this code in the Read method :

```auto
    var s *segment
	for _, segment := range l.segments {
               //The first segment we read is the oldest one. That is to say, the one
               //with a base offset equals to 0, right?
 		if segment.baseOffset <= off {
			s = segment
			break
		}
	}
	if s == nil || s.nextOffset <= off {
		return nil, fmt.Errorf("offset out of range: %d", off)
	}

```

If we try to read offset 3, by reading the first (oldest) segment in the loop, we will have: `segment.baseOffset = 0 <= 3` However, the Record with the offset 3 is in the segment which baseOffset is 2.

Did I miss something?

---

<div class="post-metadata">

**Author:** ![travisjeffery](https://forum.devtalk.com/user_avatar/forum.devtalk.com/travisjeffery/32/525_2.png) [@travisjeffery](https://forum.devtalk.com/u/travisjeffery)\
**Post date:** [10 June 2020 10:25 UTC](https://forum.devtalk.com/t/distributed-services-with-go-method-log-read-fails-reading-records/733/2 "2020-06-10T10:25:43Z")

</div>

Hey, yeah it should be implemented like this:

```auto
func (l *Log) Read(off uint64) (*api.Record, error) {
	l.mu.RLock()
	defer l.mu.RUnlock()
	var s *segment
	for _, segment := range l.segments {
		if segment.baseOffset <= off && off < segment.nextOffset {
			s = segment
			break
		}
	}
	// START: before
	if s == nil || s.nextOffset <= off {
		return nil, fmt.Errorf("offset out of range: %d", off)
	}
	// END: before
	return s.Read(off)
}

```

I fixed a ton of issues that will be in the next beta, which should be out either late this week or next week.
