Hone logo
Hone
Problems

Implement a Custom io.Writer in Go

Go's io.Writer interface is a fundamental concept for handling output streams. It allows different types of data sinks to be treated uniformly. This challenge asks you to implement your own custom io.Writer that buffers data and provides a way to retrieve the accumulated content.

Problem Description

Your task is to create a Go struct that satisfies the io.Writer interface. This struct will act as a memory buffer for any data written to it.

Key Requirements:

  1. Implement io.Writer: Your struct must have a Write(p []byte) (n int, err error) method that adheres to the io.Writer interface.
  2. Data Buffering: The Write method should append the provided byte slice p to an internal buffer.
  3. Retrieve Buffered Data: Provide a method (e.g., Bytes() []byte) to retrieve the entire content accumulated in the buffer.
  4. Error Handling: The Write method should return the number of bytes written and nil for the error if successful. For this specific implementation, assume writes are always successful unless the buffer runs out of capacity (which we'll limit for simplicity).

Expected Behavior:

When data is written to an instance of your custom writer, it should be stored. Subsequent writes should append to the existing data. The Bytes() method should return a snapshot of the data accumulated up to that point.

Edge Cases:

  • Writing an empty byte slice.
  • Writing nil byte slice.
  • Writing to a writer that has already been written to multiple times.

Examples

Example 1:

Input:
writer := NewMemoryWriter()
writer.Write([]byte("Hello, "))
writer.Write([]byte("World!"))
output := writer.Bytes()

Output:
[]byte("Hello, World!")

Explanation: The initial write appends "Hello, ". The second write appends "World!" to the existing buffer. The Bytes() method returns the concatenated result.

Example 2:

Input:
writer := NewMemoryWriter()
writer.Write([]byte{}) // Write an empty slice
output := writer.Bytes()

Output:
[]byte{}

Explanation: Writing an empty slice does not change the buffer's content.

Example 3:

Input:
writer := NewMemoryWriter()
initialData := []byte("First Part")
writer.Write(initialData)
secondWriteData := []byte(" Second Part")
writer.Write(secondWriteData)
retrievedData := writer.Bytes()

// Let's verify the data integrity
if !bytes.Equal(retrievedData, []byte("First Part Second Part")) {
    // Handle error: data mismatch
}

Explanation: Demonstrates appending data in multiple steps and verifying the final accumulated content.

Constraints

  • The internal buffer should not have a predefined hard limit for this challenge, but for practical purposes, consider that very large writes might consume significant memory.
  • The input p to the Write method will be a byte slice ([]byte).
  • Your implementation should be efficient for typical use cases.
  • The Bytes() method should return a new slice containing the buffer's data, not a reference to the internal buffer itself, to prevent external modification.

Notes

  • You will need to define a struct and implement the Write method on it.
  • Consider using a slice of bytes ([]byte) as the internal storage for your buffer.
  • The bytes package in Go's standard library might be helpful.
  • Think about how to efficiently append data to your internal buffer.
  • For the Bytes() method, ensure you return a copy to maintain data integrity.
Loading editor...
go